汇编学习(2)32位模式下NASM与GCC

32位模式下NASM与GCC

C文件依然没变:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

extern int do_something(int);

int main(int argc, char const *argv[])
{
int a = do_something(10);
printf("%d\n", a);
return 0;
}

test.asm 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
; test2.asm
[bits 32]
global _do_something
section .text
_do_something:
push ebp
mov ebp, esp
xor eax, eax
mov eax, [ebp + 0x8]
add eax, eax
mov esp, ebp
pop ebp
ret

注意do_something前的“_”,本来没有加,然后就报错了(undefined reference to `do_something')。

在谷歌上看到这么一句话:

C编译器通常会在所有外部作用域程序标识符前面加下划线,以避免与运行时语言支持的影响相冲突。 此外,当C / C ++编译器需要在外部链接中引入名称作为翻译过程的一部分时,这些名称通常以多个前导或尾部下划线的组合来区分。这种做法后来被编纂为C和C ++语言标准的一部分,其中使用领先的下划线被保留用于执行。

使用NASM:

1
$ nasm -f win32 -o test.obj test.asm

MINGW32-w32-GCC

1
$ w32gcc test.c test.obj -o test.exe

再加上IDA Pro上的反编译结果吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [esp+1Ch] [ebp-4h]

__main();
v4 = do_something(10);
printf("%d\n", v4);
return 0;
}

// =================================================

int __cdecl do_something(int a1)
{
return 2 * a1;
}