Выполнение системного вызова в GAS и использование переменных в разделе .data и доступ к ним для системного вызова в другой подпрограмме - PullRequest
0 голосов
/ 13 апреля 2020

Вот пример кода, который я написал с использованием синтаксиса GAS для 64-битной сборки Intel. Когда код запускается, вы должны распечатать строку: Внутри подпрограммы _print.

#This example is a an example to call a subroutine 
.global _start

.section .text

_start:

    call _print

_exit:   
    #exit call
    mov $60, %rax
    xor %rdi, %rdi

    syscall

_print:
    #set up the stack frame
    push %rbp
    mov %rsp, %rbp

    # write syscall's parameter set up
    mov std_out_fd, %rdi
    mov $message, %rsi
    movq message_size, %rdx
    mov write_syscall_no, %rax

    syscall

    #Restore callers registers value
    #pop %rdx
    #pop %rsi
    #pop %rdi 

    #Destroy the stack frame:
    mov %rbp, %rsp
    pop %rbp

    ret


.section .data


std_out_fd: .int 0x02

message: .ascii "Inside the _print subroutine.\n"

message_size: .byte 30

write_syscall_no: .int 0x01

=========================== ===================

Когда я пытаюсь использовать объявленную переменную 'message_size' в качестве третьего параметра для системного вызова write, я получаю несколько странные дополнительные символы, напечатанные после того, как сообщение напечатано на экране:

ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ as -o subroutine.o subroutine.s
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ld -o subroutine subroutine.o
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
`;`Qali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$

, но когда вместо использования переменной я изменяю ее на mov $ 30,% rdx

, тогда оно работает отлично, и ни один из дополнительные символы (; Q) будут больше записываться на стандартный вывод.

ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ ./subroutine
Inside the _print subroutine.
ali@alix2:~/Programming/asm/GAS-Syntax/SubRoutine$ 

Может кто-нибудь объяснить причину этого? Спасибо.

1 Ответ

1 голос
/ 13 апреля 2020

movq message_size, %rdx - это 64-битная (qword) загрузка, которая включает .byte 30, .int 0x1 и 3 байта после этого. Используйте отладчик (например, GDB) для просмотра значений в регистрах. И используйте strace ./subroutine, чтобы отслеживать системные вызовы и показывать, что вы передаете огромную длину write.

. Вы можете использовать загрузку movzbl message_size(%rip), %edx, чтобы обнулить этот байт до RDX.

Или, лучше, пусть ассемблер вычислит для вас размеры как константы времени сборки с
.equ message_size, . - message
, чтобы вы могли использовать $message_size как непосредственный. Нет необходимости отдельно кодировать размер или сохранять его в памяти данных.

То же самое для номера вызова; не выполняйте 64-битную загрузку, особенно 32-битную .int! Если после этого у вас есть какие-либо другие вещи в .data, они загрузят мусор в старшие байты RAX. Вы могли бы просто mov в EAX, который неявно распространяется на RAX.

...