将C程序转换为汇编代码

Sam*_*Sam 4 c assembly

我该如何将这个C程序转换为汇编代码?我很难理解这个过程或者如何开始它.我是新来的.任何帮助,将不胜感激!

while(a!=b){
     if(a > b){
        a = a - b;
       }
        else{
          b = b - a;
    }
  }
   return a;
   }
Run Code Online (Sandbox Code Playgroud)

附注:假设已在寄存器R0和R1中给出了两个正整数a和b.
你能发表评论解释你是怎么做到的吗?

thu*_*zas 12

教我系统编程的教授使用他所谓的'原子C'作为C和汇编之间的垫脚石.原子C的规则是(最好的回忆):

  1. 只允许使用简单表达式,即a = b + c;不允许a = b + c + d;使用,因为那里有两个运算符.
  2. if语句中只允许使用简单的布尔表达式,即if (a < b)允许但if (( a < b) && (c < d))不允许.
  3. 只有声明,没有其他阻止.
  4. 不允许/ while或do-while被允许,只有goto和标签

那么,上述计划将转化为;

 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;
Run Code Online (Sandbox Code Playgroud)

我希望我能做到这一点......自从我上次写下原子C以来已经差不多二十年了.现在假设上面的内容是正确的,让我们开始将一些原子C语句转换为MIPS(假设你正在使用的)汇编.从Elliott Frisch提供的链接,我们几乎可以立即翻译减法步骤:

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
Run Code Online (Sandbox Code Playgroud)

由于a和b都是正整数,我使用无符号减法.

比较可以这样完成:

if(a == b) goto label2 becomes if(R0 == R1) goto label2 which is: beq R0, R1, L2?
Run Code Online (Sandbox Code Playgroud)

这里的问题是beq操作码的第三个参数是PC移动的位移.在我们完成手工装配之前,我们不会知道这个价值.

不平等是更多的工作.如果我们遗留伪代码指令,我们首先需要使用set on less thanop代码,如果第一个寄存器小于第二个寄存器,则将其放在目标寄存器中.完成后,我们可以使用branch on equal上述内容.

if(a < b)              becomes    slt R2, R0, R1  
    goto label4                   beq R2, 1, L4?        
Run Code Online (Sandbox Code Playgroud)

跳转很简单,它们只是j然后跳转到的标签.所以,

goto label1 becomes j label1
Run Code Online (Sandbox Code Playgroud)

我们必须处理的最后一件事是回归.通过将我们想要的值移动到特殊寄存器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
Run Code Online (Sandbox Code Playgroud)

有了这些信息,程序就变成了.我们还可以调整之前不知道的跳跃:

           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
 0x0123        LW ret, V0                     ; move return value from RAM to the return register.
 0x0124        JR R31                         ; return to caller
Run Code Online (Sandbox Code Playgroud)

自从我不得不做这样的事情已经差不多二十年了(现在好几天,如果我需要汇编我只是做别人的建议,让编译器完成所有繁重的工作).我确信在此过程中我犯了一些错误,并且对于任何更正或建议都会感到高兴.我只是进入了这个冗长的讨论,因为我将OP问题解释为手工翻译 - 有人可能会在他们学习集会时这样做.

干杯.


CS *_*Pei 11

如果您正在使用gcc,则可以像gcc -S -o a.s a.c使用源代码一样获取程序集a.c.如果您使用的是Visual Studio,则可以在调试时通过选择"反汇编"窗口来获取它.这是Visual Studio的输出(我将subrountine/function命名为"common",这就是"common"出现的原因):

    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]  
    }
Run Code Online (Sandbox Code Playgroud)

这里变量a最初保存在内存中,因此是b(dword ptr [b]).