Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将C程序转换为汇编代码_C_Assembly - Fatal编程技术网

将C程序转换为汇编代码

将C程序转换为汇编代码,c,assembly,C,Assembly,如何将这个C程序转换成汇编代码?我很难理解这个过程,甚至无法理解如何开始它。我是新来的。任何帮助都将不胜感激 while(a!=b){ if(a > b){ a = a - b; } else{ b = b - a; } } return a; } 旁注:假设寄存器R0和R1中已经给出了两个正整数a和b。 你能留下解释你是怎么做的注释吗?如果你使用的是gcc,如果你的源代码是a.c,你可以

如何将这个C程序转换成汇编代码?我很难理解这个过程,甚至无法理解如何开始它。我是新来的。任何帮助都将不胜感激

while(a!=b){
     if(a > b){
        a = a - b;
       }
        else{
          b = b - a;
    }
  }
   return a;
   }
旁注:假设寄存器R0和R1中已经给出了两个正整数a和b。

你能留下解释你是怎么做的注释吗?

如果你使用的是
gcc
,如果你的源代码是
a.c
,你可以将程序集设置为
gcc-S-o a.S a.c
。如果您使用的是Visual Studio,则可以在调试时通过选择“反汇编”窗口获得它。下面是Visual studio的输出(我将子计数器/函数命名为“common”,这就是“common”出现的原因):


这里变量
a
最初保存在内存中,
b
dword ptr[b]
)。

教我系统编程的教授使用了他所谓的“原子C”作为C和汇编之间的垫脚石。原子C的规则是(据我记忆所及):

  • 只允许使用简单表达式,即
    a=b+c
    a=b+c+d,因为有两个运算符
  • if语句中只允许使用简单的布尔表达式,即允许使用
    if(a
    ,但不允许使用
    if((a
  • 只有if语句,其他语句都不会阻塞
  • 不允许使用for/while或do-while,只允许使用goto和label
  • 因此,上述方案将转化为:

     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;
    
    我使用了无符号减法,因为a和b都是正整数

    可通过以下方式进行比较:

    if(a == b) goto label2 becomes if(R0 == R1) goto label2 which is: beq R0, R1, L2?
    
    这里的问题是,beq op代码的第三个参数是PC移动的位移。在这里手工组装完成之前,我们不会知道这个值

    不平等是更多的工作。如果我们离开伪代码指令,我们首先需要使用小于
    操作码上的
    设置,如果第一个寄存器小于第二个寄存器,则在目标寄存器中放入一个。完成此操作后,我们可以如上所述使用equal上的
    分支

    if(a < b)              becomes    slt R2, R0, R1  
        goto label4                   beq R2, 1, L4?        
    
    我们要处理的最后一件事是退货。返回是通过移动我们想要的值来完成的 一个特殊寄存器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
     0x0123        LW ret, V0                     ; move return value from RAM to the return register.
     0x0124        JR R31                         ; return to caller
    
    L1:
    0x0100 BEQ R0、R1、8
    0x0104 SLT R2、R0、R1;温度=(a
    我已经有将近二十年没有做过这样的事情了(现在已经有一天了,如果我需要汇编,我就按照别人的建议去做,让编译器来完成所有繁重的工作)。我确信我在这一过程中犯了一些错误,如果有任何更正或建议,我将非常高兴。我之所以进行这种冗长的讨论,是因为我把OP问题解释为做手工翻译——有些人在学习汇编时可能会做这件事


    干杯。

    我已将该代码翻译为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
    
    我用
    ax
    代替
    r0
    bx
    代替
    r1

    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
    
    尝试在这里执行代码。只需将其复制到主函数中,在
    循环之前定义
    a
    b
    变量即可


    您可以通过大量的解释了解代码是如何编译成汇编的,然后您可以在一个假想的CPU中执行汇编代码。

    虽然这是编译器的任务,但如果您想弄脏手,请查看

    这是一个很棒的编译器资源管理器工具,可以让您将C/C++代码逐行转换为汇编代码


    如果您是初学者,想知道“C程序如何转换为汇编?”那么我已经就此写了一篇详细的文章。

    使用C编译器选项生成汇编代码。请阅读以下答案:我打赌您正在学习的课程是使用MIPS汇编。你不会找到很多熟悉MIPS的专业人士。只要学习它。
    gcc-sfoo.c
    @Oregon Trail,为什么您认为许多专业人士缺乏MIPS组装经验?如果没有别的,很多人都参加过类似的课程,或者读过MIPS作为学习汇编语言和操作系统概念的模型系统的书。谢谢!我试图理解编译器,而破解gcc或其他编译器生成的汇编代码是一件非常痛苦的事情!顺便问一下,名字重要吗?我知道我是说加载到寄存器中,但是在汇编代码中,beqa,B,8有效吗?我假设你指的是寄存器的名称。如果是的话,那么它们确实很重要。汇编程序应该在BEQ A,B,8上抛出一个错误,除非您已经将A和B定义为某物。所以,让我弄清楚,汇编指令的所有操作数名称都来自预定义的集合(表示寄存器)?i、 e.它
               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
    
    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
    
    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