本文重点只是介绍怎么使用GCC和NASM混合编译16位的纯二进制文件,包括汇编调用C函数 C调用汇编。。。
编译环境:Windows,所以linux下的朋友不需要MinGW
1.MinGW
//GCC
__asm__(".code16gcc\n");
extern int puts(char * str);//申明汇编函数
int main(char * message)
{
return puts(message);
}
;;;nasm
extern main
global puts
global entry
[bits 16]
entry:
jmp next_entry;入口地址
@MESSAGE: db 'This is the test message !',0x0d,0x0a,0
;========================================================================================================================
;函数 puts
;功能 打印字符串
;堆栈:
; |-----------------------|
; | [ebp+8] | 目标字符串的段地址
; | [ebp+4] | 返回地址
; | [ebp+0] | --> push ebp
; |-----------------------|
;========================================================================================================================
puts:
push ebp
mov ebp, esp
push esi
push eax
push ebx
mov esi, [ebp+0x08]
.@1:
lodsb ; 从 ds:si中读入一个字符到 al
or al, al ; 检测字符是否为0
jz .@2 ; 显示完毕, 退出过程
mov ah, 0x0e
mov bl, 0x09
int 0x10
jmp short .@1
.@2:
pop ebx
pop eax
pop ebp
db 0x66
ret
next_entry:
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, 0xfff0
push dword @MESSAGE
call dword main
add sp, 4
int 0x20
编译命令:
gcc -c -o main.o main.c
nasm -f elf -o entry.o entry.s
ld -s --entry=entry -Ttext=0x7c00 -o example.elf entry.o main.o ;-Ttext=0x7c00 指明将程序装载到内存0x7c00处 --entry=entry 指明入口点
objcopy -I elf32-i386 -O binary -S example.elf example.com
这样编译出来的不是512字节 因为是引导程序 所以我们要用ultraedit 填充满512字节 最后两个改成0x55aa;
PS:
感谢 骨骨猫儿的指导和代码。。。