目前共有18篇帖子。
【方法】在Linux C程序中嵌入彙編語言
12樓 巨大八爪鱼 2016-2-26 14:43
彙編語言中的除法指令:
【彙編部分】
GLOBAL div
div:
    MOV AX, [ESP+4]
    DIV BYTE[ESP+8]
    RET
【C語言部分】
#include <stdio.h>
short div(unsigned char a, unsigned char b);
int main()
{
    short num = div(10, 3);
    printf("%d ... %d\n", num & 0xff, num >> 8);
    return 0;
}
運行結果:
3 ... 1
13樓 巨大八爪鱼 2016-2-26 15:22
在彙編語言中調用C語言函數:
【彙編部分】
GLOBAL fun
fun:
    CALL [ESP+4]
    RET
【C語言部分】
#include <stdio.h>
void fun(void (*f)());
void test()
{
    printf("This is a string.\n");
}
int main()
{
    fun(test);
    return 0;
}
輸出:
This is a string.
14樓 巨大八爪鱼 2016-2-26 16:14
彙編語言創建C語言可寫的數組的方法:
【彙編部分】
SECTION .bss
GLOBAL arr
arr:
    RESB 20
【C語言部分】
#include <stdio.h>
#include <string.h>
extern char arr[20];
int main()
{
    strcpy(arr, "This is a string.");
    puts(arr);
    return 0;
}

輸出:
This is a string.
15樓 巨大八爪鱼 2016-2-26 16:27
關於彙編語言中的三個段:
【彙編部分】
; BSS段中專門存放未初始化的變數
SECTION .bss
GLOBAL arr
arr:
    RESB 20

; 這個段中不可以定義函數
;fun3:
;    RET

; DATA段中專門存放已初始化的變數
; 其中的內容可讀可寫
SECTION .data
GLOBAL msg
msg:
    DB "Hello, World!"
    DB 0

GLOBAL fun2
fun2:
    RET

; TEXT段中的內容是只讀的
SECTION .text
GLOBAL str
GLOBAL fun
str:
    DB "abcdef"
    DB 0
fun:
    MOV EAX, 14
    RET
【C語言部分】
#include <stdio.h>
#include <string.h>
extern char arr[20];
extern char msg[];
extern char str[];
int fun();
void fun2();
int main()
{
    strcpy(arr, "This is a string.");
    puts(arr);
   
    msg[0] = 'I';
    puts(msg);
    printf("%d\n", fun());
   
    //str[0] = 'm'; // 只讀!將會引發段錯誤
    puts(str);
   
    fun2();   
    return 0;
}
【輸出】
This is a string.
Iello, World!
14
abcdef
16樓 巨大八爪鱼 2016-2-26 16:41
接下來我們來一點刺激的!
把一個C語言數組拿來執行!

【C語言部分】
#include <stdio.h>
#include <string.h>

extern char fun, end; // fun函數的開始和結束位置
char codes[200];

int main()
{
    int size = &end - &fun; // fun函數的機器代碼大小
    printf("size=%d\n", size);
    memcpy(codes, &fun, size); // 把fun函數的機器代碼複製到codes數組中
   
    // 執行codes數組中所存放的機器代碼,並讀取代碼執行完畢後EAX暫存器中的值
    int (*fun)() = (int (*)())codes;
    int v = fun();
    printf("%d\n", v);
   
    return 0;
}
【彙編部分】
GLOBAL fun
GLOBAL end
fun:
    MOV EAX, 48
    RET
end:

【運行結果】
size=6
48
17樓 巨大八爪鱼 2016-2-26 16:43
int (*fun)() = (int (*)())codes;
這句話的意思就是:先定義一個fun變數,變數的類型為函數指針。
然後把codes變數(本來是一個數組)強行轉換成函數指針,賦給fun變數。
18樓 巨大八爪鱼 2016-2-26 16:48
16樓所示的代碼有點沒寫好,因為main函數中有兩個fun,所以乾脆改一個名字吧,更容易理解:
#include <stdio.h>
#include <string.h>

extern char fun, end; // fun函數的開始和結束位置
char codes[200];

int main()
{
    int (*fff)(); // 定義一個函數指針
    int v;
    int size = &end - &fun; // fun函數的機器代碼大小
    printf("size=%d\n", size);
    memcpy(codes, &fun, size); // 把fun函數的機器代碼複製到codes數組中
   
    // 執行codes數組中所存放的機器代碼,並讀取代碼執行完畢後EAX暫存器中的值
    fff = (int (*)())codes;
    v = fff();
    printf("%d\n", v);
   
    return 0;
}
19樓 巨大八爪鱼 2016-2-26 16:55
實際上,不需要定義函數指針,就能直接執行codes數組:
v = ((int (*)())codes)();
printf("%d\n", v);
只不過括號比較多而已。

回復帖子

內容:
用戶名: 您目前是匿名發表
驗證碼:
 
 
©2010-2024 Arslanbar [手機版] [桌面版]
除非另有聲明,本站採用創用CC姓名標示-相同方式分享 3.0 Unported許可協議進行許可。