将FOR转换为汇编程序

时间:2009-11-07 22:14:57

标签: c assembly x86

我需要将方法中注释的内容翻译成汇编程序。我有一个大致的想法,但不能。

有人可以帮我吗?适用于Intel x32架构:

int 
secuencia ( int n, EXPRESION * * o )
{
  int a, i;
//--- Translate from here ...
  for ( i = 0; i < n; i++ ){
    a = evaluarExpresion( *o );
    o++;
  }
  return a ;
//--- ... until here.
}

翻译的代码必须在__asm中:

__asm {
        translated code
}

谢谢,

最终更新:

这是最终版本,工作和评论,感谢所有人的帮助:)

int
secuencia ( int n, EXPRESION * * o )
{
    int a = 0, i;
    __asm
    {
        mov dword ptr [i],0             ; int i = 0
        jmp salto1
        ciclo1:
        mov eax,dword ptr [i]           
        add eax,1                       ; increment in 1 the value of i
        mov dword ptr [i],eax           ; i++
        salto1: 
        mov eax,dword ptr [i]           
        cmp eax,dword ptr [n]           ; Compare i and n
        jge final                       ; If is greater goes to 'final'
        mov eax,dword ptr [o] 
        mov ecx,dword ptr [eax]         ; Recover * o (its value)
        push ecx                        ; Make push of * o (At the stack, its value)
        call evaluarExpresion           ; call evaluarExpresion( * o )
        add esp,4                       ; Recover memory from the stack (4KB corresponding to the * o pointer)
        mov dword ptr [a],eax           ; Save the result of evaluarExpresion as the value of a
        mov eax,dword ptr [o]           ; extract the pointer to o
        add eax,4                       ; increment the pointer by a factor of 4 (next of the actual pointed by *o)
        mov dword ptr [o],eax           ; o++
        jmp ciclo1                      ; repeat
        final:                          ; for's final
        mov eax,dword ptr [a]           ; return a - it save the return value at the eax registry (by convention this is where the result must be stored)
    }
}

4 个答案:

答案 0 :(得分:8)

基本上在汇编语言中,严格来说,没有循环的概念与更高级语言中的相同。它都是通过跳转实现的(例如,作为“goto”......)

也就是说,x86有一些指令,假设您将编写“循环”,隐式使用寄存器ECX作为循环计数器。

一些例子:

    mov ecx, 5         ; ecx = 5
.label:
    ; Loop body code goes here
    ; ECX will start out as 5, then 4, then 3, then 1...
    loop .label        ; if (--ecx) goto .label;

或者:

    jecxz .loop_end    ; if (!ecx) goto .loop_end;
.loop_start:
    ; Loop body goes here
    loop .loop_start   ; if (--ecx) goto .loop_start;
.loop_end:

并且,如果你不喜欢这个loop指令向后倒计时......你可以写下这样的东西:

    xor ecx, ecx       ; ecx = 0
.loop_start:
    cmp ecx, 5         ; do (ecx-5) discarding result, then set FLAGS
    jz .loop_end       ; if (ecx-5) was zero (eg. ecx == 5), jump to .loop_end
    ; Loop body goes here.
    inc ecx            ; ecx++
    jmp .loop_start
.loop_end:

这将更接近典型的for (int i=0; i<5; ++i) { }

答案 1 :(得分:6)

请注意

for (init; cond; advance) {
    ...
}

基本上是语法糖

init;
while(cond) {
   ...
   advance;
}

如果你在课堂上一直在关注,那么它应该很容易翻译成汇编语言。

答案 2 :(得分:5)

使用gcc生成汇编代码

gcc -S -c sample.c

man gcc是你的朋友

答案 3 :(得分:2)

为此,您可能会使用循环指令在每个循环中递减ecx(通常称为扩展计数器)并在ecx达到零时熄灭。但是为什么还要使用内联asm呢?我非常确定一些简单的东西会被编译器正确优化......

(我们说x86架构,因为它基于80x86计算机,但它是一个“ok”错误= p)