Вот методика, позволяющая ответить на некоторые вопросы, подобные этим, для любой архитектуры, для которой установлена установленная копия GCC. Используйте флаг -S
, чтобы получить исходный файл сборки для подходящего фрагмента кода. В качестве альтернативы используйте -Wa,-al
, чтобы получить список сборок, показывающий фактические байты, сгенерированные ассемблером. Например,
int foo(char var) {
if (var == 'x')
return 42;
return 17;
}
компилируется с gcc -c -Wa,-al
на моем ПК с Windows для создания
GAS LISTING C:\DOCUME~1\Ross\LOCALS~1\Temp/ccyDNLLe.s page 1
1 .file "q3715034.c"
2 .text
3 .p2align 4,,15
4 .globl _foo
5 .def _foo; .scl 2; .type 32;
.endef
6 _foo:
7 0000 55 pushl %ebp
8 0001 31C0 xorl %eax, %eax
9 0003 89E5 movl %esp, %ebp
10 0005 807D0878 cmpb $120, 8(%ebp)
11 0009 5D popl %ebp
12 000a 0F94C0 sete %al
13 000d 48 decl %eax
14 000e 83E0E7 andl $-25, %eax
15 0011 83C02A addl $42, %eax
16 0014 C3909090 ret
16 90909090
16 90909090
Линии 7 и 9 - это все, что осталось от котельной пластины входа функции, а линии 11 и 16 - котельная плита выхода функции. Строка 8 очищает весь регистр возвращаемого значения до 0. Строка 10 - это фактическое сравнение var == 'x'
, и вы можете увидеть магическое число $120
в инструкции cmpb $120, 8(%ebp)
; код ASCII для 'x'
равен 120 десятичному или 0x78 в шестнадцатеричном виде. Вы можете увидеть 0x78 в сегменте .text со смещением 8, где он хранится как часть инструкции CMPB. В остальной части тела реализован выбор возвращаемых значений из моего образца фрагмента, используя инструкцию SETE, чтобы сделать AL
равным 1, если сравнение было истинным, или 0 в противном случае. Остальные инструкции DECL
, ANDL
и ADDL
затем генерируют 17 или 42 в зависимости от начального значения регистра AL
во всем регистре EAX
, в котором хранятся возвращаемые значения из целочисленных функций. в этой архитектуре.