本文目錄一覽:
彙編語言與C語言轉換
程序有很多問題,做了部分修改
#includereg51.h
#define uchar unsigned char
sbit p10=P1^0;
sbit p30=P3^0;
sbit p31=P3^1;
sbit p12=P1^2;
void delay()
{
uchar i,j;
for(i=0;i170;i++)
for(i=0;i187;i++);
}
void alarm()
{
uchar times;
p12=1;
p30=0;
p31=0;
times=0x14;
TMOD=0x01;
TH0=0x3c;
TL0=0xb0;
TR=1;
while(times)
{
while(TF0==0);
TF0=0;
TH0=0x3c;
TL0=0xb0;
times–;
}
p30=1;
p31=0;
p12=0;
}
void pint0() interrupt 0
{
EX0=0;
if(p32==0)
{
delay();
if(p32==0)
{
p30=1;
p31=0;
p12=0;
}
}
EX0=1;
}
main()
{
IE=0x81;
IT0=1;
SP=0x30;
p30=1;
p31=1;
P1=0xff;
P2=0x00;
p12=0;
while(1)
{
if(p10==0)
{
delay();
if(p10==0)alarm();
}
}
}
單片機C51,將彙編語言轉換為C語言
#includereg52.h
#define u8 unsigned char
#define u16 unsigned int
#define BufSize 0x10
u8 buf[BufSize];
u8 js=0;
void main(){
SCON=0x80;
PCON=0x80;
EA=1;
ES=1;
ACC=buf[0];
TB8=P;
SBUF=ACC;
while(1);
}
void TRANI()interrupt 4
{
TI=0;
js++;
if(js==BufSize){
ES=0;
}
else{
ACC=buf[js];
TB8=P;
SBUF=ACC;
}
}
順便優化彙編代碼
BUF EQU 0X50
ORG 0000H
JMP MAIN
ORG 0023H
JMP TRANI
MAIN:
MOV SCON,#0X80;
MOV PCON,#0X80
SETB EA
SETB ES
MOV R0,#BUF
MOV A,@R0
MOV C,P
MOV TB8,C
MOV SBUF,A
JMP $
TRANI:
PUSH PSW
PUSH ACC
INC R0
CJNE R0,#BUF+0x10,NEXT
JMP TEND
NEXT: MOV A,@R0
MOV C,P
MOV TB8,C
MOV SBUF,A
TEND:
POP ACC
POP PSW
RETI
如何將這段彙編語言轉換成C語言
如何將這段彙編語言轉換成C語言?題目分別提供了同一C語言代碼的32位和64位彙編版本:很容易可以得出其源C語言代碼:
int f(int** p){
return (**p=**p+4,*(int*)**p);
}
則函數體的返回值類型是int,參數p的類型是int**,其唯一的語句是return (**p=**p+4,*(int*)**p);
先把結論放在這,節約不想思考的同學的時間,不同編譯器可能會有所不同,lea 0x4(%eax),%ecx指令可能會被編譯器拆開成兩段:mov (%eax),%ecx 和add 0x4,%ecx(對於64位,則是編譯器把lea lea 0x4(%rax),%rcx,拆開成mov (%rax),%rcx 和add 0x4,%rcx,但是效果是一樣的。
根據題目中函數體只有1句代碼的信息,我們至少確定了這個代碼是一個return語句,如此短小的函數當然只需要用到段內跳轉和段內指針,不需要段地址信息,所以指針大小(64位的RIP和32位的EIP)只是偏移量大小,分別為64位(8字節)和32位(4字節)。
題目的設問有相當好的引導性,對比查看左邊和右邊的倒數第3個指令,我們可以看出:函數的返回值都是放在eax變量之中,說明返回值的類型大小是4個字節。而同時,我們知道在C語言中,64位和32位環境下,int類型的大小都是4個字節,所以第1空的答案不能是只有1字節的char類型,也不能是在32位環境下大小為4字節而在64位環境下大小為8字節的指針類型如char*、int*。綜上,第1空的答案:函數f的返回值類型只能是int。
第2空則是考查C語言函數的參數傳遞,棧式參數傳遞,在call函數f把ip壓入(分別為64位的RIP和32位的EIP)之前,先壓入的是函數的實際參數,其類型暫時不知道,那就得從彙編指令中找出這個信息點:
C語言函數體標誌就是:push %ebp→mov %esp,%ebp→函數體內部→pop %ebp→ret(對64位則是:push %rbp→mov %rsp,%rbp→函數體內部→pop %rbp→retq)
兩邊都是同一個簡單的c語句得到的彙編語句(64位和32位),左邊64位的第2、3、4行對應於右邊的第2、3行(64位多用了一個rdi寄存器傳遞參數,可能是編譯器選項不同的緣故,又因為main函數中調用函數f的指令沒有給出,且不一定相同,故不影響判斷)。
兩邊剩下的幾行代碼(左邊2、3、4、5、6、7、8行,右邊2、3、4、5、6、7行)的工作大同小異,從數據流上看(函數體內,對於32位0x8(%ebp)是第一個也是唯一一個參數,對於64位-0x8(%rbp)才是):
*p→eax,*eax→eax,eax+4→ecx(①),*p→edx,ecx→*edx,*eax→eax
可以簡化為:
**p→eax,eax+4→ecx,ecx→**p,***p→eax
再簡化為
**p+4→**p,***p→eax
註:(①)lea 0x4(%eax), %ecx 意思是取有效地址Load Effect Address,相比於mov 0x4(%eax), %ecx使用地址所指向的值*(eax+4)→ecx,lea指令只使用地址的值eax+4→ecx,少做一步。64位也是如此a。
(對於64位則是:
*p→rax,*rax→rax,rax+4→rcx,*p→rdx,rcx→*rdx,*rax→eax
可以簡化為:
**p→rax,rax+4→rcx,rcx→**p,***p→eax
再簡化為
**p+4→**p,***p→eax
)
看到數據流了,C語言語句自然也就呼之欲出了,即return (**p=**p+4,*(int*)**p)。(逗號,運算符的意思是從左到右計算式子,然後返回最後一個)
注意這裡的+4指的是4個字節,而在64位32位中都一樣,於是初步斷定**p是固定大小類型變量,同時返回值是int類型的,故認為它(**p)是int,所以參數p的類型就是int**。
請問如何把彙編語言轉成C語言
反過來是可以的,叫反彙編,但彙編無法轉C,因為彙編是機器語言,C最終還是轉化成彙編,想轉的話只能人為的編一個C出來
怎麼把彙編轉換成C語言
如果 只是簡單的幾行,可以把編譯後的exe文件,用系統自帶的debug(windows鍵+R打開 運行窗口 輸入debug 空格 exe的路徑)打開debug後,輸入U可以看到幾行彙編代碼。
如果是源代碼 在vs編譯器中調試運行,菜單上的:調試–窗口–反彙編 可以查看,如果是其他編譯器 仔細找找也帶反彙編的
要資料的話 [天書夜讀-從彙編語言到Windows內核編程].譚文.邵堅磊. 這本書的基礎部分里 有c語言與彙編的轉換
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/248427.html