asm
ddatsh
asm
demo
hello world
section .data
hello db "hello world!", 0xa, 0
section .text
global main; // 程序入口点,要调c的库函数要用main,否则链接时提示找不到main
main:
push dword hello ;; //c函数参数传递放在栈中
extern printf
call printf ; // 调用外部函数的作用
add esp, byte 4 ;; // 事实上这是一个出栈动作,以让程序找到正确的地址进行返回
ret
nasm -f elf hello.asm -o hello.o
tcc hello.o -o hello.exe -m32
1 加到 100
section .data
format db "%d", 0xa, 0;
section .text
global main
main:
mov eax, 0
mov ecx, 100
l:
add eax, ecx
loop l
;mov eax, (1+100)*100/2;
extern printf
push dword eax;
push dword format; printf(const char*,...);
call printf
add esp, byte 8
ret
win32
STD_OUTPUT_HANDLE equ -11
NULL equ 0
global main
extern ExitProcess, GetStdHandle, WriteConsoleA
section .data
msg db "Hello World!", 13, 10, 0
msg.len equ $ - msg
section .bss
dummy resd 1
section .text
main:
push STD_OUTPUT_HANDLE
call GetStdHandle
push NULL
push dummy
push msg.len
push msg
push eax
call WriteConsoleA
push NULL
call ExitProcess
http://www.godevtool.com/Golink.zip
nasm -f win32 hello.asm -o hello.obj
GoLink.exe /console /entry GobleyGook hello.obj kernel32.dll
tcc只支持elf格式,gcc/vc的是coff格式
汇编格式
主要列一些 AT&T 和 intel 汇编区别
- 相反的源和目标操作数次序、立即数 $
Intel:mov eax, 4
AT&T:movl $4, %eax
- 操作数大小标识
Intel:mov al, byte ptr foo
AT&T:movb foo, %al
一个用 byte ptr ,一个用 movb
汇编器区别
masm , nasm
; masm 编译器自动加上:
; push ebp
; mov ebp,esp
;masm
mov edi,[PVal]; 与 mov edi,PVal 结果一样
mov eax,[var1]; 与 mov eax,var1 结果一样
Nasm最接近编译后的程序,MASM在源码上方便了程序的代码编写操作,但隐藏太多底层的细节
可执行文件格式
os 读可 ELF 文件头部,找到标记为可加载(loadable)的段,调 mmap()把段内容加载到内存中,段标记作用内存中是否可读、可写,可执行
a.out 不适应共享库,COFF可包含更多的段,但对动态连接和C++程序的支持仍然比较困难
unix 开发出 ELF格式,作为ABI(应用和内核底层接口)
比如有初始化段.init和结束段.fini(对应构和析构函数)支持C++
ABI
- 数据类型的大小、布局和对齐
- 调用约定(函数参数如何传送以及如何接受返回值),如参数通过栈传递,还是部分参数通过寄存器传递;哪个寄存器用于哪个函数参数;通过栈传递的第一个函数参数是最先push到栈上还是最后
- 系统调用的编码和一个应用如何向操作系统进行系统调用
- C++ 名称修饰
API 对应源码的可编译,ABI对应目标文件的可直接运行