在程序集中使用int rand(void)

时间:2011-11-22 12:07:27

标签: assembly x86

我正在尝试使用该功能

int rand(void)

在集会中。

我该如何使用它?我希望得到0到20之间的随机数。

我该怎么做?

我正在使用Ubuntu 32位操作系统并使用at& t汇编语法。 这是我的代码示例,我希望它在%edx注册表中添加0到20之间的随机数。

编辑:

    mov $APPLES_X, %ebx
    mov $0, %ecx
    mov $20, %edx
loop_ax:
    call    rand
    idiv    %edx
    mov %edx, (%ebx)

    add $4, %ebx

    inc %ecx
    cmp NAPPLES, %ecx
    jne loop_ax

2 个答案:

答案 0 :(得分:6)

对于这类问题,最好的办法是让编译器为您完成大部分工作。例如。使用gcc,你可以使用gcc -S为一个小样本C程序生成汇编程序源代码,该程序已经完成了你想做的事情:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int x = rand();
    printf("x = %d\n", x);
    return 0;
}

生成程序集:

$ gcc -Wall -S -O3 -m32 rand.c -o rand.S

你得到:

    .file   "rand.c"
    .section    .rodata.str1.1,"aMS",@progbits,1
.LC0:
    .string "x = %d\n"
    .text
    .p2align 4,,15
.globl main
    .type   main, @function
main:
    leal    4(%esp), %ecx
    andl    $-16, %esp
    pushl   -4(%ecx)
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ecx
    subl    $20, %esp
    call    rand
    movl    $.LC0, (%esp)
    movl    %eax, 4(%esp)
    call    printf
    addl    $20, %esp
    xorl    %eax, %eax
    popl    %ecx
    popl    %ebp
    leal    -4(%ecx), %esp
    ret
    .size   main, .-main
    .ident  "GCC: (SUSE Linux) 4.3.4 [gcc-4_3-branch revision 152973]"
    .section    .comment.SUSE.OPTs,"MS",@progbits,1
    .string "OspWg"
    .section    .note.GNU-stack,"",@progbits

所以看起来你只需要:

    call    rand

,结果将在EAX

如果要将随机数的范围限制为0..20,请在上面的C程序中实现,彻底测试,然后重复上述过程以生成具有此附加功能的汇编源。

答案 1 :(得分:3)

您的原始代码并不遥远。请记住以下事项:

  1. rand()是标准的库函数,因此您需要将程序链接到该程序,否则找不到函数/可执行文件无法运行。
    如果使用gcc将程序集文件“编译”为可执行文件,和/或使用gcc将汇编程序生成的*.o文件链接到可执行文件中,则所有必需的依赖库将是必要时添加。
    如果您尝试使用ld ...进行手动链接,则需要了解所有这些内容并手动指定。
  2. 在UN * X上,%edx暂存寄存器(保留调用者),当您进行函数调用时会被覆盖。所以你必须向下移动mov $20, %edx两行,在<{em> call rand后执行
  3. 另一个临时寄存器%ecx,因此您无法将循环计数器保留在%ecx中,除非您在{{之前/之后/之后将其保存/恢复到堆栈中1}}。
    将循环计数器移动到非易失性(被呼叫者保留)寄存器,而不是call rand%esi%edi%ebp。当然,如果您选择在函数中使用这些寄存器,则还必须添加代码以保存/恢复然后在函数的进入/退出时。
  4. 除此之外,正如Paul所提到的,从编译器输出中学习总是一个好主意,特别是在汇编的情况下从优化的编译器输出中学习。你不需要编译为asm,只需编译成可执行文件,然后运行%ebx来反汇编整个东西。