Ассемблер - c-язык и мнемоника
Я написал простую программу на языке c, классический helloworld. Я хотел знать, как это выглядело, когда компилятор переводил его в ассемблерный код.
Я использую MinGW и команду:
gcc -S hellow.c
Когда я открыл этот файл, я ожидал, что он будет, по крайней мере, несколько похож на программу hello-world, написанную непосредственно на ассемблере, а именно:
jmp 115
db 'Hello world!$' (db = define bytes)
-a 115
mov ah, 09 (09 for displaying strings ... ah = 'command register')
mov dx, 102 (adress of the string)
int 21
int 20
Вместо этого это выглядит так:
.file "hellow.c"
.def ___main;
.scl 2;
.type 32;
.endef
.section
.rdata,"dr"
LC0:
.ascii "Hello world!\0"
.text
.globl _main
.def _main;
.scl 2;
.type 32;
.endef
_main:
LFB6:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
call ___main
movl $LC0, (%esp)
call _puts
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE6:
.def _puts;
.scl 2;
.type 32;
.endef
Я немного знаю о языке ассемблера, но я ДОЛЖЕН распознавать так называемые мнемоники, такие как ADD, POP, PUSH, MOV, JMP, INT и т. Д. Не могу увидеть большинство из них в коде, сгенерированном c-компилятором.
Что я не понял?
2 ответа
Ваш пример кода использует Intel
синтаксис, в то время как стандартный вывод от gcc AT&T
синтаксис. Вы можете изменить это с помощью
gcc -S hellow.c -masm=intel
Полученный результат должен выглядеть более знакомым.
Однако, если компилятор генерирует исходный код, он выглядит несколько иначе, чем то, что вы написали бы от руки.
int
будет использоваться, если вы компилируете для DOS, но даже в этом случае эти вызовы будут заключены в стандартные функции C, например puts
в этом случае.
Это подготавливает аргументы для вызова функции __main
это, вероятно, делает все начальные настройки, необходимые для программы на C
andl $-16, %esp
subl $16, %esp
call ___main
Это готовит аргументы и вызывает функцию _puts
, LC0
является символом, который содержит строку для печати.
movl $LC0, (%esp)
call _puts
Это готовит возвращаемое значение main
и возвращается
movl $0, %eax
leave
ret