Вывод сброшенной сборки g ++ не работает

У меня есть следующий код C ++ в файле main.cpp.

int add(int a,int b)
{
int c = a + b;
return c;
}int main()
{
int a = 2;
int b = 4;
int d = add(2,4);
}

когда я запустил g ++ -S main.cpp, я получил следующий код сборки (после удаления всех символов отладки). Также я изменил код для вывода суммы 2 чисел с помощью системного вызова sys_write.

.text
.globl  _Z3addii
_Z3addii:
pushq   %rbp
movq    %rsp, %rbp
movl    %edi, -20(%rbp)
movl    %esi, -24(%rbp)
movl    -24(%rbp), %eax
movl    -20(%rbp), %edx
addl    %edx, %eax
movl    %eax, -4(%rbp)
movl    -4(%rbp), %eax
popq    %rbp
ret
.globl  main

main:
pushq   %rbp
movq    %rsp, %rbp
subq    $16, %rsp
movl    $2, -12(%rbp)
movl    $4, -8(%rbp)
movl    $4, %esi
movl    $2, %edi
call    _Z3addii
movl    %eax, -4(%rbp)

movl    $4, %edx            #message length
movl    -4(%rbp), %esi      #message to write
movl    $1, %edi            #file descriptor (stdout)
movl    $1, %eax            #system call number (sys_write)
syscall                     #call kernel

movl    $60, %eax           # Invoke the Linux 'exit' syscall
movl    $0, %edi            # With a return value of 0
syscall                     # call kernel
ret

Моя проблема, когда я запускаю вышеупомянутую сборку, она ничего не дает в качестве вывода. Я не могу понять, что мне здесь не хватает? Может кто-нибудь сказать мне, что мне не хватает? Благодарю.

используемые команды:
g ++ -o main main.s и ./main -> нет вывода

ОС: Ubuntu 12.04 64bit и g ++ версия: 4.8.2

1

Решение

Есть две вещи, которые вы делаете неправильно:

Во-первых, вы — 64-битная инструкция syscall, но инициализируете только %e часть регистров. Во-вторых, это:

movl    -4(%rbp), %esi

загружает значение, которое в -4(%rbp) (6 вы только что рассчитали) в %esi, когда sys_write ожидает адрес памяти этого значения там (под которым я имею в виду в %rsi). Это работает с этим:

movq    $1, %rax            #system call number (sys_write)
movq    $1, %rdi            #file descriptor (stdout)
leaq    -4(%rbp), %rsi      #message to write
movq    $4, %rdx            #message length
syscall                     #call kernel

Конечно, вы не получите форматированный вывод таким способом. Чтобы увидеть, что 6 напечатан, вам нужно будет передать вывод через hexdump или что-то подобное.

Приложение: что вы только инициализируете %e часть регистров на самом деле только очень важно здесь в случае %rsi, %rbp во время чтения содержит значение с установленными старшими битами, и они теряются, если только -4(%ebp) написано %esi, Технически это также работает:

movl    $1, %eax            #system call number (sys_write)
movl    $1, %edi            #file descriptor (stdout)
leaq    -4(%rbp), %rsi      #message to write
movl    $4, %edx            #message length
syscall                     #call kernel

…но я чувствую, что это довольно плохой стиль.

3

Другие решения


По вопросам рекламы [email protected]