c語言調用匯編
『壹』 c語言里如何調用匯編里的變數
語言混編一般是模塊化的,模塊之間相對獨立的,不能直接調用,必須遵循一定的約定,才能將模塊融合為一體;各種編程語言的共通點就是代碼編譯後最終都成為機器代碼,當然也可以用匯編語言作為中間代碼,再由匯編代碼編譯成機器代碼;比如說C語言寫成dll形式,另的語言調用dll來完成代碼共用。要在c語言里調用匯編里的變數,首先要理解匯編里的變數是如何存放的,因為C語言的實現又跟操作系統有關,所以又必須理解C語言在這個系統里是如何實現的。用匯編語言寫個call,c語言里按照這個call約定調用這個call,就可以調用call裡面的變數了。
『貳』 C語言寫的程序 怎麼反匯編成匯編語言
在keilc中,單片機的C語言程序可以再DEBUG模式中得到對應的匯編程序。步驟如下:
1、建立工程,導入C文件代碼,編譯生成hex文件。
3、點擊View--Disassembly Window調出匯編窗口,如上圖。
通過以上步驟就可以看到與C對應的匯編程序了。
『叄』 如何用匯編實現C語言函數調用
1。對於「匯編調用」:
我知道你要調用func,而不是它本身,但如果這個函數比較復雜時是必須用逆向先分析func這個函數,然後再確定參數列表和返回值的……
2。對於你的內聯匯編的代碼:
這里到底要不要用add %3, %%rsp;還是一個問題,因為要看函數使用的是什麼調用標准,有標准C的,VB的,Pascal的,包括fastcall,stdcall,cdecl等……
3。對於「知道函數參數的起始地址和長度」:
這個的話,除了參數中有字元數組和直接結構體什麼的,所有的基本變數基本都是每8位元組(64位)一個,並且Intel一般都用bigendian的,也就是說,在內存中 01 02 03 04 05 06 07 08 讀入寄存器後會變為: 0x0807060504030201
所以說對於簡單的函數,用8位元組一個參數來做就好了……
而對於有字元數組什麼的就必須用逆向分析了……
這個……只能進行逆向分析了……
反正你知道了函數的地址和長度……
就是你把編譯為機器碼的程序用反編譯工具翻譯成匯編,然後分析一下就好了,C語言的匯編還是比較簡單……
比如這個函數:
int func(int a, int* b) {
// float要用到CPU的FPU,指令記不得,要查下
// 為了簡單就改為int*
printf("a = %d, b = %d\n", a, *b);
return a;
}
編譯成機器碼後,反編譯,如果不加優化,一般都會這樣:
(假設函數入口地址為0400000h)
sub_0400000:
push rbp
mov rbp,rsp ; C函數參數度取使用堆棧式
; 參數在內存中這樣: |...| a | b | ... |
; 由於是64位,故8位元組對齊
mov rax,[rbp+8] ; rax = *(rbp+8) // 這里就是 rax = a
push rsi
mov rsi,[rbp+16] ; rsi = *(rbp+16) // rsi = b
; 調用C函數都是這樣堆棧式,最後一個參數最先入棧
push [rsi]
push rax
push "a = %d, b = %d\n" ; 這里是便於理解,實際上是push這個字元串常量的指針
call printf ; printf("a = %d, b = %d\n",rax,*rsi)
add rsp,24 ; 平衡堆棧,用了3個參數,要還原3*8=24位元組,但根據函數類型的不同去平衡,像調用VB的函數就不需要平衡堆棧……
; 還原數據
mov rsp,rbp
pop rsi
pop rbp
; 一般返回數據都用rax裝載
mov rax,[rbp+8] ;rax=a
ret ; return rax
想調用未知參數列表的函數就是把以上過程倒過來,看著匯編把C的代碼寫出來……
破解注冊碼什麼也是這樣玩的……
實際上你可以直接用反編譯的軟體,比如IDA,直接自動分析,它反編譯的雖然是匯編,但參數列表還是大部分都顯示的……
但是,當編譯器加優化大部分情況就必須自己分析了,因為:
int func(int a, int* b) {
printf("a = %d, b = %d\n", a, *b);
return a;
}
在優化情況下可能為(直接用寄存器傳遞數據):
sub_040000:
push rdx
mov rdx,rax
push rax
push rbx
push "a = %d, b = %d\n"
call printf
mov rax,rdx
pop rdx
ret
其實像www.pediy.com看雪學院有不少這方面的教程……