1. 程式人生 > 實用技巧 >自制作業系統(5)彙編的C的相互呼叫

自制作業系統(5)彙編的C的相互呼叫

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