У меня есть следующий код 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
Есть две вещи, которые вы делаете неправильно:
Во-первых, вы — 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
…но я чувствую, что это довольно плохой стиль.