2014-09-29 153 views
3

如何將該C程序轉換爲彙編代碼?我很難理解這個過程或如何啓動它。我是新來的。任何幫助,將不勝感激!將C程序轉換爲彙編代碼

while(a!=b){ 
    if(a > b){ 
     a = a - b; 
     } 
     else{ 
      b = b - a; 
    } 
    } 
    return a; 
    } 

側注:假設在寄存器R0和R1中已經給出了兩個正整數a和b。
你可以留下評論,解釋你是如何做到的嗎?

+8

使用C編譯器選項生成彙編代碼。 – 2014-09-29 02:11:39

+0

閱讀以下答案:http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem – 2014-09-29 02:12:25

+0

我敢打賭,你正在使用的課程是使用MIPS程序集。你不會找到許多熟悉MIPS的專業人士。只要學習它。 – OregonTrail 2014-09-29 02:13:11

回答

9

如果您使用的是gcc,那麼如果您的源代碼是a.c,則可以獲得程序集爲gcc -S -o a.s a.c。如果您使用的是Visual Studio,您可以通過選擇「反彙編」窗口進行調試。下面是Visual Studio中的輸出(I起名叫做「常用」 subrountine /功能,這就是爲什麼「共同」出現):

while(a!=b){ 
    003613DE mov   eax,dword ptr [a] 
    003613E1 cmp   eax,dword ptr [b] 
    003613E4 je   common+44h (0361404h) 
     if(a > b){ 
    003613E6 mov   eax,dword ptr [a] 
    003613E9 cmp   eax,dword ptr [b] 
    003613EC jle   common+39h (03613F9h) 
      a = a - b; 
    003613EE mov   eax,dword ptr [a] 
    003613F1 sub   eax,dword ptr [b] 
    003613F4 mov   dword ptr [a],eax 
     } 
     else{ 
    003613F7 jmp   common+42h (0361402h) 
      b = b - a; 
    003613F9 mov   eax,dword ptr [b] 
    003613FC sub   eax,dword ptr [a] 
    003613FF mov   dword ptr [b],eax 
     } 
     } 
    00361402 jmp   common+1Eh (03613DEh) 
     return a; 
    00361404 mov   eax,dword ptr [a] 
    } 

這裏變量a最初保存在內存中,因此是bdword ptr [b])。

8

教授我係統編程的教授使用他所謂的'atomic-C'作爲C和彙編之間的墊腳石。用於原子-C的規則(據我的記憶):

  1. 只有簡單的表達式允許的,即a = b + c;允許a = b + c + d;是不允許的,因爲有兩家運營商那裏。
  2. 在if語句中只允許使用簡單的布爾表達式,即允許if (a < b),但不允許if ((a < b) && (c < d))
  3. 只有語句,沒有別的塊。
  4. 沒有了/是允許做的,而同時,或只轉到的和標籤的

因此,上述計劃將翻譯成;

label1: 
    if (a == b) 
     goto label2; 

    if (a < b) 
     goto label4; 

    a = a - b; 
    goto label3; 

label4: 
    b = b - a; 

label3: 
    goto label1; 

label2: 
    return a; 

我希望我得到了正確的......它已經將近二十年,因爲我最後不得不寫原子-C。現在假設上面的說法是正確的,讓我們開始將一些atomic-C語句轉換爲MIPS(假設這就是你正在使用的)程序集。由埃利奧特·弗裏施提供的鏈接,我們幾乎可以立即翻譯減法步驟:

a = a - b  becomes R0 = R0 - R1 which is: SUBU R0, R0, R1 
b = b - a  becomes R1 = R1 - R0 which is: SUBU R1, R1, R0 

我用無符號減法,由於A和B是正整數。

的比較可正是如此做:

if(a == b) goto label2 becomes if(R0 == R1) goto label2 which is: beq R0, R1, L2? 

的這裏的問題是,BEQ操作碼的第三個參數是位移的PC移動。在我們完成這裏的手工組裝之前,我們不會知道這個價值。

不平等是更多的工作。如果我們離開了僞代碼指令,我們首先需要使用set on less than操作碼,如果第一個寄存器小於第二個寄存器,那麼將其中一個放入目標寄存器。一旦我們完成了,我們可以使用branch on equal如上所述。

if(a < b)    becomes slt R2, R0, R1 
    goto label4     beq R2, 1, L4?   

跳轉很簡單,它們只是j,然後是跳轉到的標籤。所以,

goto label1 becomes j label1 

我們必須處理的最後一件事是回報。返回是通過將我們想要的值移動到特殊寄存器V0,然後在調用此函數後跳轉到下一條指令完成的。問題是MIPS沒有註冊移動命令的註冊表(或者如果它忘了它),所以我們從寄存器移動到RAM然後再移回。最後,我們使用保存返回地址的特殊寄存器R31。

return a  becomes var = a  which is SW R0, var 
         ret = var which is LW var, V0 
         jump RA  which is JR R31 

有了這些信息,程序就變成了。而且我們還可以調整,我們並不知道之前的跳躍:

  L1: 
0x0100  BEQ R0, R1, 8 
0x0104  SLT R2, R0, R1     ; temp = (a < b) temp = 1 if true, 0 otherwise 
0x0108  LUI R3, 0x01     ; load immediate 1 into register R3 
0x010C  BEQ R2, 1, 2     ; goto label4   
0x0110  SUBU R0, R0, R1    ; a = a - b 
0x0114  J L3       ; goto label3 
      L4: 
0x0118  SUBU R1, R1, R0    ; b = b - a; 
      L3: 
0x011C  J L1       ; goto lable1 
      L2: 
0x0120  SW R0, ret      ; move return value from register to a RAM location 
0xLW ret, V0      ; move return value from RAM to the return register. 
0x0124  JR R31       ; return to caller 

它已經將近二十年以來,我不得不做這樣的東西(現在是一個天,如果我需要組裝我只是做別人的建議,並讓編譯器完成所有繁重的工作)。我相信我一路上犯了一些錯誤,並會很樂意提供任何更正或建議。我只進入了這個冗長的討論,因爲我把OP問題解釋爲做手工翻譯 - 有人可能會在學習裝配時做的事情。

歡呼聲。

+0

謝謝!我試圖理解編譯器,並且破譯由gcc或其他編譯器生成的彙編代碼非常痛苦!順便說一句名字很重要?我知道我說加載到寄存器,但在彙編代碼中,是說BEQ A,B,8有效嗎? – 2016-04-21 20:39:28

+0

我假設你的意思是寄存器的名稱。如果是這樣,那麼他們確實很重要。你的彙編程序應該在'BEQ A,B,8'上拋出一個錯誤,除非你已經定義了A和B。 – thurizas 2016-04-22 14:47:09

+0

因此,讓我明白這一點,彙編指令的所有操作數名稱都來自預定義的集合(代表寄存器)?即彙編器的任務不是將任意名稱映射到寄存器,即這是在編譯時完成的嗎? – 2016-04-22 22:15:46

1

我翻譯的代碼爲16位NASM彙編:

loop: 
    cmp ax, bx 
    je .end;  if A is not equal to B, then continue executing. Else, exit the loop 
    jg greater_than; if A is greater than B... 

    sub ax, bx;  ... THEN subtract B from A... 

    jmp loop;  ... and loop back to the beginning! 

.greater_than: 
    sub bx, ax;  ... ELSE, subtract A from B... 

    jmp loop;  ... and loop back to the beginning! 

.end: 
    push ax;  return A 

我代替r0bx用於替代axr1

0
ORG 000H     // origin 
MOV DPTR,#LUT    // moves starting address of LUT to DPTR 
MOV P1,#00000000B   // sets P1 as output port 
MOV P0,#00000000B   // sets P0 as output port 
MAIN: MOV R6,#230D   // loads register R6 with 230D 
     SETB P3.5   // sets P3.5 as input port 
     MOV TMOD,#01100001B // Sets Timer1 as Mode2 counter & Timer0 as Mode1 timer 
     MOV TL1,#00000000B // loads TL1 with initial value 
     MOV TH1,#00000000B // loads TH1 with initial value 
     SETB TR1    // starts timer(counter) 1 
BACK: MOV TH0,#00000000B // loads initial value to TH0 
     MOV TL0,#00000000B // loads initial value to TL0 
     SETB TR0    // starts timer 0 
HERE: JNB TF0,HERE   // checks for Timer 0 roll over 
     CLR TR0    // stops Timer0 
     CLR TF0    // clears Timer Flag 0 
     DJNZ R6,BACK 
     CLR TR1    // stops Timer(counter)1 
     CLR TF0    // clears Timer Flag 0 
     CLR TF1    // clears Timer Flag 1 
     ACALL DLOOP   // Calls subroutine DLOOP for displaying the count 
     SJMP MAIN   // jumps back to the main loop 
DLOOP: MOV R5,#252D 
BACK1: MOV A,TL1   // loads the current count to the accumulator 
     MOV B,#4D   // loads register B with 4D 
     MUL AB    // Multiplies the TL1 count with 4 
     MOV B,#100D   // loads register B with 100D 
     DIV AB    // isolates first digit of the count 
     SETB P1.0   // display driver transistor Q1 ON 
     ACALL DISPLAY  // converts 1st digit to 7seg pattern 
     MOV P0,A   // puts the pattern to port 0 
     ACALL DELAY 
     ACALL DELAY 
     MOV A,B 
     MOV B,#10D 
     DIV AB    // isolates the second digit of the count 
     CLR P1.0   // display driver transistor Q1 OFF 
     SETB P1.1   // display driver transistor Q2 ON 
     ACALL DISPLAY  // converts the 2nd digit to 7seg pattern 
     MOV P0,A 
     ACALL DELAY 
     ACALL DELAY 
     MOV A,B    // moves the last digit of the count to accumulator 
     CLR P1.1   // display driver transistor Q2 OFF 
     SETB P1.2   // display driver transistor Q3 ON 
     ACALL DISPLAY  // converts 3rd digit to 7seg pattern 
     MOV P0,A   // puts the pattern to port 0 
     ACALL DELAY   // calls 1ms delay 
     ACALL DELAY 
     CLR P1.2 
     DJNZ R5,BACK1  // repeats the subroutine DLOOP 100 times 
     MOV P0,#11111111B 
     RET 

DELAY: MOV R7,#250D  // 1ms delay 
DEL1: DJNZ R7,DEL1 
     RET 

DISPLAY: MOVC A,@A+DPTR // gets 7seg digit drive pattern for current value in A 
     CPL A 
     RET 
LUT: DB 3FH    // LUT starts here 
    DB 06H 
    DB 5BH 
    DB 4FH 
    DB 66H 
    DB 6DH 
    DB 7DH 
    DB 07H 
    DB 7FH 
    DB 6FH 
END 
+0

彙編彙編到C編程 – denish 2017-02-17 11:27:50

+0

需要適當的格式並添加一些描述來解釋 – jjj 2017-02-17 11:44:33

+0

這個問題正在尋找*解釋*,而不僅僅是工作代碼。您的回答對提問者沒有任何洞察力,並且可能會被刪除。請[編輯]解釋導致觀察到的症狀的原因。 – 2017-02-17 13:25:45

0

https://ctoassembly.com

嘗試在這裏執行你的代碼。只需將它複製到主函數中,在while循環之前定義變量ab,您就可以輕鬆完成任務。

您可以看到如何將代碼編譯爲程序集並進行大量解釋,然後才能在假設的CPU內執行彙編代碼。