;hello.asm 仅仅适用于win32控制台程序
;nasm -f win32 -o hello.o hello.asm
;gcc -o hello.exe hello.o
bits 32 ;这似乎不是必须的,但nasm还可以编译16位程序及16、32位
;混合编程的程序,所以在32位程序中习惯上加上这个
;这里定义了一个宏,以模拟enter指令,nasm似乎没有这个指令
%ifndef ENTER
%define ENTER
%macro enter 0
push ebp
mov ebp, esp
%endmacro
%endif
global _main ;因为要用到gcc链接,这里应该把此处的main标记为全局标号
extern _printf ;从c标准库中引用的过程,因此标记为外部标号
section .text ;正文段,这似乎是必须的,否则无法链接
_main:
enter
sub esp, 0x20 * 4 ;在栈中预留出32个空间
mov eax, [esp + 0x20 * 4 + 2 * 4];获取int main(int argc, char* argv[])
;函数的第一个参数, 即argc, 这个参数
;为命令行被空格分隔字符串的个数
mov [c], eax
mov dword [esp + 0 * 4], str ;第一个参数入栈,虽然没有参考过printf函数的原型
;但基本知道大概是void printf(const char* s, ...),
;返回值类型没有深究过,第一行参数为常字符串(为
;可变参数提供格式化字符串),后面为若干个参数
mov eax, [i]
mov dword [esp + 1 * 4], eax ;第二个参数入栈
mov eax, [c]
mov dword [esp + 2 * 4], eax ;第三个参数入栈
;下面是上述两条指令的”等价形式“
;push dword [i]
;push str
call _printf
;一般的为了不破坏栈,若采用”等价形式“需要在call指令后加入如下类似的指令
;add esp, 2 * 4
add esp, 0x20 * 4 ;释放在栈中预留的空间
leave ;恢复栈值,相当于用下面的两条指令,详见nasm手册
;mov esp, ebp
;pop ebp
ret
align 32
section .data ;数据段
str: db 'Hello, World! %d %d', 0xa, 0 ;格式化参数字符串,可以看出printf
;在实际中第一个参数后又有两个参数
i dd 0x378
align 32
section .bss ;未初始化段
c resd 1
nasm的Hello, World!程序应该这么写(Win32控制台)
猜你喜欢
转载自blog.csdn.net/weixin_39410618/article/details/103543511
今日推荐
周排行