无法在程序集x86中找出printf函数并使用操作数

时间:2015-11-03 22:27:09

标签: assembly printf nasm exponentiation

我已经对发布这个问题感到紧张,但现在就这样了。我试图设计一个汇编程序来接受两个整数,然后接受一个操作数(*,+或^)。然后,根据操作数,程序将根据所选的操作数执行算术序列。输出必须看起来完全像这样,让我们​​说用户输入5,然后用户输入6,最后用户输入一个*,程序必须打印出来

OP 5 * 6 = 30

现在,由于某些原因我无法理解printf的概念,所以我的打印功能在底部是我试图打印出来的荒谬方式。如果有人能向我解释printf是如何工作的,我很乐意听到它!我对堆栈有非常基本的了解。另外,我没有这方面的指数函数,因为我不知道如何用汇编语言来做。最后,我对那些真正的计算机神有一个非程序相关的问题......我非常讨厌汇编语言,我在用这种语言编写基本操作时遇到了麻烦。我喜欢在C,CPP和Java工作......这个语言对于日常的程序员来说是绝对必要的,或者这是关于人们在打火机之前如何着火的历史课程?无论如何,欢迎任何问题的答案,并提前感谢。

;program to add, multiply, or give the power of a number

%include "asm_io.inc"


segment .data 


prompt1 db    "Enter a number: ", 0        ;prompts
prompt2 db    "Enter another number: ", 0
prompt3 db    "Enter an operand", 0
prompt4 db    "OP ", 0    ;idiotic prompts for printing
prompt5 db    " = ", 0    ;another printing prompt

segment .bss

num1  resd 1    ;variable for 1st number
num2  resd 1    ;variable for 2nd number
op    resd 1    ;variable for operand


segment .text

    global  asm_main
asm_main:
    enter   0,0               ; setup routine
    pusha

    restart:
        mov     eax, prompt1      ; print out prompt
        call    print_string
        call    print_nl

        call    read_int          ; read integer
        mov     [num1], eax       ; store into num1
        call    print_nl

        mov     eax, prompt2      ; print out prompt
        call    print_string
        call    print_nl

        call    read_int          ; read integer
        mov     [num2], eax     ; store into num2
        call    print_nl

        mov     eax, promtp3    ;print out prompt
        call    print_string
        call    print_nl

        call    read_char       ;read operand and dispose of null
        call    read_char
        mov     [op], eax       ;store operand in [op]
        call    print_nl

        cmp     [op], '*'       ;operand comparison
        jne     jmp1
        call    mulFun
        jmp     restart

jmp1:   cmp     [op], '+'       ;operand comparison
        jne     jmp2
        call    sumFun
        jmp     restart

jmp2:   cmp     [op], '^'       ;operand comparison
        jne     jmp3
        call    expFun
        jmp     restart

jmp3:   cmp     [op], 'e'       ;exit function
        je      end1

end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    call    print_nl          ; pr
    popa
    mov     eax, 0            ; return back to C
    leave
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mulfun:                     ;multiplication function
    mov     ebx, [num1]
    mov     ecx, [num2]
    imul    ebx, ecx
    jmp     printFun

sumFun:                     ;sum function
    mov     ebx, [num1]
    mov     ecx, [num2]
    add     ebx, ecx
    call    printFun


printFun:                   ;printing function
    mov     eax, [prompt4]
    call    print_string
    mov     eax, [num1]
    call    print_string
    mov     eax, [op]
    call    print_string
    mov     eax, [num2]
    call    print_string
    mov     eax, [prompt5]
    call    print_string
    mov     eax, ebx
    call    print_string
    call    print_nl
    ret

1 个答案:

答案 0 :(得分:4)

到处都发现了我在评论中添加***的问题。有几点需要注意:

  • 您的某些标签中存在拼写错误
  • NASM 区分大小写,因此 mulfun mulFun 不同。
  • 如果您的指令带有一个或多个不涉及寄存器(对于src或目标)但引用内存的操作数,则需要指定内存操作数的大小。例如,cmp [op], '+'必须指定数据 [op] 引用的大小,因此您可以在其前面加上大小。大小可以是字节 dword 。您正在比较单个字符,因此大小将是 byte 。代码应该看起来像cmp byte [op], '+'
  • 如果你有一个变量并且你mov eax, varname这会将 varname 的地址移动到 EAX 。如果要移动 varname 的内容,则必须使用mov eax, [varname]等方括号括起来。处理字符串地址和 print_string 例程时,您需要传递 EAX 中字符串的地址,而不是内容。所以请忽略括号。
  • 如果您使用call来调用某个函数,则您的函数应以ret结尾。
  • 请勿jmp使用call
  • 如果要打印字符,请不要使用 print_string ,请使用 print_char 。将角色放在 EAX
  • 如果要打印整数,请不要使用 print_string ,请使用 print_int 。将整数放在 EAX

修订后的代码如下:

;program to add, multiply, or give the power of a number

%include "asm_io.inc"

segment .data

prompt1 db    "Enter a number: ", 0        ;prompts
prompt2 db    "Enter another number: ", 0
prompt3 db    "Enter an operand", 0
prompt4 db    "OP ", 0    ;idiotic prompts for printing
prompt5 db    " = ", 0    ;another printing prompt

segment .bss

num1  resd 1    ;variable for 1st number
num2  resd 1    ;variable for 2nd number
op    resd 1    ;variable for operand


segment .text

    global  asm_main
asm_main:
    enter   0,0                 ; setup routine
    pusha

    restart:
        mov     eax, prompt1    ; print out prompt
        call    print_string
        call    print_nl

        call    read_int        ; read integer
        mov     [num1], eax     ; store into num1
        call    print_nl

        mov     eax, prompt2    ; print out prompt
        call    print_string
        call    print_nl

        call    read_int        ; read integer
        mov     [num2], eax     ; store into num2
        call    print_nl

        mov     eax, prompt3    ;print out prompt
                                ;*** Typo - promtp3 changed to prompt3
        call    print_string
        call    print_nl

        call    read_char       ;read operand and dispose of null
        call    read_char
        mov     [op], eax       ;store operand in [op]
        call    print_nl

        cmp     byte [op], '*'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp1
        call    mulFun
        jmp     restart

jmp1:   cmp     byte [op], '+'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp2
        call    sumFun
        jmp     restart

jmp2:   cmp     byte [op], '^'  ;operand comparison
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        jne     jmp3
;        call    expFun         ;*** This expFun function doesn't exist so
                                ;*** don't call it so we can compile and link
        jmp     restart

jmp3:   cmp     byte [op], 'e'  ;exit function
                                ;*** We must specify the size of data we are
                                ;*** comparing, so we tell the assembler that
                                ;*** with 'byte' in front of the variable
        je      end1

end1:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    call    print_nl          ; pr
    popa
    mov     eax, 0            ; return back to C
    leave
    ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
mulFun:                     ;multiplication function
                            ;*** NASM is case sensitive - changed mulfun to mulFun
    mov     ebx, [num1]
    mov     ecx, [num2]
    imul    ebx, ecx
    call    printFun        ;*** Call printFun, don't 'jmp' to it
    ret                     ;*** Since mulfun was called, we use 'ret' to return

sumFun:                     ;sum function
    mov     ebx, [num1]
    mov     ecx, [num2]
    add     ebx, ecx
    call    printFun
    ret

printFun:                   ;printing function
    mov     eax, prompt4    ;*** We want the address of prompt4, not what is at prompt4
                            ;*** Remove the brackets from [prompt4]
    call    print_string
    mov     eax, [num1]
    call    print_int       ;*** Use print_int to print an integer, not print_string
    mov     eax, [op]
    call    print_char      ;*** Use print_char to print a char, not print_string
    mov     eax, [num2]
    call    print_int       ;*** Use print_int to print an integer, not print_string
    mov     eax, prompt5    ;*** We want the address of prompt5, not what is at prompt5
                            ;*** Remove the brackets from [prompt5]
    call    print_string
    mov     eax, ebx
    call    print_int       ;*** Use print_int to print an integer, not print_string;
    call    print_nl
    ret

我将把它留给原始海报来开发 expFun 功能。目前我已对其进行了评论,因此可以组装,链接和运行现有代码。

你可以使用 printf ,但我认为漫长的方式也可以教一些东西,我从我的回答中排除了对 printf 的讨论。您的导师,课程材料,教师助理将是您开始解决其他问题的好地方。

提供此答案是为了让您的程序进入可用状态,以便您可以继续进行分配。在我看来,原来的问题太宽泛了。如果需要进一步的帮助,最好提出具体问题的新问题。