自制作業系統(5)彙編的C的相互呼叫
阿新 • • 發佈:2020-11-14
C語言結合彙編開發核心
- CentOS/Ubuntu
- Nasm For Linux
- gcc
- objconv
C語言編譯後的彙編程式碼必須是保護模式,所以上一節強調了保護模式
簡單的結合
一個簡單的C語言程式碼:
bar.c
extern void foo_print(char* p, int len); // 判斷兩個數大小然後輸出 int bar_func(int a, int b) { if (a > b) { foo_print("the 1st one\n", 13); } else { foo_print("the 2nd one\n", 13); } return 0; }
彙編程式碼:
foo.asm
extern bar_func ;C語言編寫的函式名 [section .data] ;C語言函式傳的兩個引數 arg1 dd 3 arg2 dd 4 [section .text] ;這裡暫時記下來必須這樣寫 global _start global foo_print ;C語言中extern的函式名 _start: mov eax, dword[arg1] ;C語言傳參規則:最右面的引數先壓棧(3) push eax mov eax, dword[arg2] ;實際上C語言的第一個引數是arg2(4) push eax call bar_func add esp, 8 ;清除壓入的8個位元組 mov ebx,0 mov eax, 1 int 0x80 ;系統呼叫,告訴系統執行完畢表示退出 foo_print: ;匯出給C語言用的函式 mov edx, [esp + 8] ;要列印的字串的長度 mov ecx, [esp + 4] ;ecx儲存要列印的字串的內容 mov ebx, 1 mov eax, 4 int 0x80 ;系統呼叫,列印相關的功能 ret
開啟CentOS
nasm -f elf32 foo.asm -o foo.o
gcc -m32 -c -o bar.o bar.c
ld -m elf_i386 -o foobar foo.o bar.o
./foobar
成功打印出the 1st one
反彙編方式
剛才的結合使檔案變成了elf格式,系統核心不能執行elf,所以考慮將C語言反彙編
https://github.com/vertis/objconv
g++ -o objconv -O2 src/*cpp(g++如果用不了自行配置)
gcc -m32 -fno-asynchronous-unwind-tables -s -c -o bar.o bar.c
./objconv -fnasm bar.o -o bar.asm
得到bar.asm但是不能直接使用,需要小改:
; Disassembly of file: ../bar.o
; Sun Nov 8 02:38:12 2020
; Mode: 32 bits
; Syntax: YASM/NASM
; Instruction set: 80386
;global bar_func: function
;extern foo_print ; near
SECTION .text align=1 execute ; section number 1, code
bar_func:; Function begin
push ebp ; 0000 _ 55
mov ebp, esp ; 0001 _ 89. E5
sub esp, 24 ; 0003 _ 83. EC, 18
mov eax, dword [ebp+8H] ; 0006 _ 8B. 45, 08
cmp eax, dword [ebp+0CH] ; 0009 _ 3B. 45, 0C
jle ?_001 ; 000C _ 7E, 16
mov dword [esp+4H], 13 ; 000E _ C7. 44 24, 04, 0000000D
mov dword [esp], ?_003 ; 0016 _ C7. 04 24, 00000000(d)
call foo_print ; 001D _ E8, FFFFFFFC(rel)
jmp ?_002 ; 0022 _ EB, 14
?_001: mov dword [esp+4H], 13 ; 0024 _ C7. 44 24, 04, 0000000D
mov dword [esp], ?_004 ; 002C _ C7. 04 24, 0000000D(d)
call foo_print ; 0033 _ E8, FFFFFFFC(rel)
?_002: mov eax, 0 ; 0038 _ B8, 00000000
leave ; 003D _ C9
ret ; 003E _ C3
; bar_func End of function
SECTION .data align=1 noexecute ; section number 2, data
SECTION .bss align=1 noexecute ; section number 3, bss
SECTION .rodata align=1 noexecute ; section number 4, const
?_003: ; byte
db 74H, 68H, 65H, 20H, 31H, 73H, 74H, 20H ; 0000 _ the 1st
db 6FH, 6EH, 65H, 0AH, 00H ; 0008 _ one..
?_004: ; byte
db 74H, 68H, 65H, 20H, 32H, 6EH, 64H, 20H ; 000D _ the 2nd
db 6FH, 6EH, 65H, 0AH, 00H ; 0015 _ one..
小改foo.asm:
;extern bar_func 去掉這個宣告
[section .data]
arg1 dd 3
arg2 dd 4
[section .text]
global _start
global main ;start改為main
main: ;start改為main
mov eax, dword[arg1]
push eax
mov eax, dword[arg2]
push eax
call bar_func
add esp, 8
mov ebx,0
mov eax, 1
int 0x80
foo_print:
mov edx, [esp + 8]
mov ecx, [esp + 4]
mov ebx, 1
mov eax, 4
int 0x80
ret
%include "bar.asm" ;最後一行加入這個
nasm -f elf32 foo.asm -o foo.o
gcc -m32 foo.o -o foo
./foo