組裝

2011-11-22 42 views
2

使用int蘭特(無效)我想使用的功能組裝

int rand(void) 

組裝。

我該如何使用它?我想獲得0到20之間的隨機數。

我該怎麼做?

我正在使用Ubuntu 32位操作系統並使用& 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 
+3

您至少需要指定您正在使用的CPU架構,操作系統和編譯器/彙編器。 –

+0

對不起,完全忘了。我正在使用Ubuntu 32位。和at&t語法。圖書館已經包括在內。我只想知道如何調用函數以及如何使用返回的值。 – Bewn

+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程序實現這個上面,對其進行全面測試,然後重複上述過程,產生與這一附加功能彙編源。

+0

非常感謝您的幫助!我會牢記這一點! :) – Bewn

3

你的原單的代碼已經不遠了。請記住以下幾點:

  1. rand()是一個標準庫函數,所以你需要你的程序與鏈接或沒有找到函數/可執行文件無法運行。
    如果使用gcc將彙編文件「編譯」爲可執行文件,和/或使用gcc將彙編程序生成的*.o文件鏈接到可執行文件,則必要時將添加所有必需的相關庫文件。
    如果您嘗試使用ld ...你需要了解所有這些和手工指定它們手工鏈接。
  2. 在UN * X上,%edx臨時寄存器(調用程序保留),在您進行函數調用時會被覆蓋。所以,你已經到了mov $20, %edx兩線向下移動,做call rand後。
  3. 另一個暫存寄存器%ecx,因此你不能保持循環計數器%ecx除非你保存/它call rand後從堆棧之前恢復到/ /。
    移動循環計數器到非易失性(被調用方保留)寄存器代替,無論是%esi%edi%ebp%ebx。當然,如果你選擇在你的函數中使用這些寄存器,你還必須添加代碼來保存/恢復,然後在你的func的入口/出口處。

除此之外,正如保羅所說,它總是一個好主意,從編譯器輸出的學習,特別是在組件的情況下優化編譯器輸出。您不需要編譯成asm,只需編譯爲可執行文件,然後運行objdump -d <name of program>即可反彙編所有內容。

+0

非常感謝!你的答案非常有幫助! :)問題現在解決了! :) – Bewn