将 C 代码转换为数组的程序集

Converting c code into assembly for arrays

我目前正在学习如何将 C 代码转换为汇编 x86 64 位代码。我的代码是:

long add_arrays(long *arr1, long *arr2, unsigned long num, long *result)
{
    unsigned long sum = 0, i = 0; 
    while(i < num) {
        result[i] = arr1[i] + arr2[i]; 
        sum = sum + result[i]; 
        i++;
    }
    return sum; 
}

当我将它转换为汇编时,我得到的输出是 0 或地址编号。我的代码是:

        .global add_arrays_asm

add_arrays_asm:
        xor %r8, %r8

while_start:
        cmp %r8, %rdx
        jge while_break

        movq (%rdi, %r8, 8), %r9 
        addq (%rsi, %r8, 8), %r9 
        movq (%rcx, %r8, 8), %r10 
        movq (%r9, %r8, 8), %rcx 
        addq (%r10, %r8, 8), %rax 
        addq (%rcx,%r8, 8),  %rax
        inc %r8
        jmp while_start

while_break:
        ret

我用来测试它的代码是:

printf("Testing add_arrays_asm\n");
    long l3[] = {3, 23, 32, 121, 0, 43, 95, 4};
    long l4[] = {-823,12,-1222,84834, -328, 0, 9, -1387};
    long res1[] = {0, 0, 0, 0, 0, 0, 0, 0}; 
    long sum1 = add_arrays_asm(l3, l4, 8, res1); 
    int j = 0; 
    for(j = 0; j < 8; j++) {
        printf("%8ld + %8ld = %8ld\n", l3[j], l4[j], res1[j]); 
    }
    printf("        Sum = %ld\n\n", sum1); 

我不熟悉汇编代码,所以我找不到代码哪里出错了。任何帮助,将不胜感激。谢谢。

你的条件跳转不正确。

    cmp %r8, %rdx
    jge while_break

这意味着

if (rdx >= r8)
    break;

所以你什么都不计算就直接break了循环。此外,您应该使用 jae 而不是 jge 进行无符号比较,因为您将其声明为 unsigned long num。尽管如果该值没有溢出最大有符号整数以至于它为负数,这可能不是问题。

另一件事,您的加载和存储似乎不正确。除此之外,您最好将内存访问保持在最低限度,如果您真的不需要它,则无需从内存中重新加载。

此外,您忘记将 %rax 归零,您应该在计算开始时有 sum = 0

解决这个问题

我修改了你的汇编代码。

func.S


.section .text
.global add_arrays_asm

add_arrays_asm:
    #rdi -> arr1
    #rsi -> arr2
    #rdx -> num
    #rcx -> result
    #r8 -> i

    xorl    %r8d, %r8d          # i = 0
    xorl    %eax, %eax          # sum = 0
while_start:
    cmpq    %rdx, %r8           # if (i >= num)
    jae     while_break         #   goto while_break

    movq    (%rdi, %r8, 8), %r9 # r9  = arr1[i]
    addq    (%rsi, %r8, 8), %r9 # r9 += arr2[i]
    movq    %r9, (%rcx, %r8, 8) # result[i] = r9
    addq    %r9, %rax           # sum += r9
    incq    %r8                 # i++
    jmp     while_start         # goto while_start

while_break:
    ret

main.c


#include <stdio.h>

long add_arrays_asm(long *arr1, long *arr2, unsigned long num, long *result);

int main()
{
    printf("Testing add_arrays_asm\n");
    long l3[] = {3, 23, 32, 121, 0, 43, 95, 4};
    long l4[] = {-823,12,-1222,84834, -328, 0, 9, -1387};
    long res1[] = {0, 0, 0, 0, 0, 0, 0, 0}; 
    long sum1 = add_arrays_asm(l3, l4, 8, res1); 
    int j = 0; 
    for(j = 0; j < 8; j++) {
        printf("%8ld + %8ld = %8ld\n", l3[j], l4[j], res1[j]); 
    }
    printf("        Sum = %ld\n\n", sum1); 
}

执行

ammarfaizi2@integral:/tmp/testz$ gcc -Wall -Wextra func.S main.c -o main
ammarfaizi2@integral:/tmp/testz$ valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./main
==748530== Memcheck, a memory error detector
==748530== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==748530== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==748530== Command: ./main
==748530== 
Testing add_arrays_asm
       3 +     -823 =     -820
      23 +       12 =       35
      32 +    -1222 =    -1190
     121 +    84834 =    84955
       0 +     -328 =     -328
      43 +        0 =       43
      95 +        9 =      104
       4 +    -1387 =    -1383
        Sum = 81416

==748530== 
==748530== HEAP SUMMARY:
==748530==     in use at exit: 0 bytes in 0 blocks
==748530==   total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==748530== 
==748530== All heap blocks were freed -- no leaks are possible
==748530== 
==748530== For lists of detected and suppressed errors, rerun with: -s
==748530== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
ammarfaizi2@integral:/tmp/testz$