汇编错误A2075:跳转目标太远:在LOOP指令上跳过25个字节

时间:2017-09-20 09:57:08

标签: loops assembly x86

我收到了这个错误:

loop    AdderLoop
  

错误A2075:跳转目标太远:按25个字节

这是一个加法器程序。

我还在学习poppush所以也许我做的不对,但似乎我的变量ARRAY_SIZE没有正确存储?

我在程序开始处按下存储ARRAY_SIZE的寄存器,并在程序结束时将其弹出。

.386      ;identifies minimum CPU for this program

.MODEL flat,stdcall    ;flat - protected mode program
                       ;stdcall - enables calling of MS_windows programs

;allocate memory for stack
;(default stack size for 32 bit implementation is 1MB without .STACK directive 
;  - default works for most situations)

.STACK 4096            ;allocate 4096 bytes (1000h) for stack

;*******************MACROS********************************

;mPrtStr
;usage: mPrtStr nameOfString
;ie to display a 0 terminated string named message say:
;mPrtStr message

;Macro definition of mPrtStr. Wherever mPrtStr appears in the code
;it will  be replaced with 

mPrtStr  MACRO  arg1    ;arg1 is replaced by the name of string to be displayed
         push edx
         mov edx, offset arg1    ;address of str to display should be in dx
         call WriteString        ;display 0 terminated string
         pop edx
ENDM

;*************************PROTOTYPES*****************************

ExitProcess PROTO,
    dwExitCode:DWORD    ;from Win32 api not Irvine to exit to dos with exit code

ReadChar PROTO          ;Irvine code for getting a single char from keyboard
                        ;Character is stored in the al register.
                        ;Can be used to pause program execution until key is hit.

WriteDec PROTO          ;Irvine code to write number stored in eax
                        ;to console in decimal

WriteString PROTO       ;Irvine code to write null-terminated string to output
                        ;EDX points to string

WriteChar PROTO         ;write the character in al to the console

;************************  Constants  ***************************

    LF         equ     0Ah                   ; ASCII Line Feed

;************************DATA SEGMENT***************************

.data
    carryIn    byte 0,0,0,0,1,1,1,1
    inputA     byte 0,0,1,1,0,0,1,1
    inputB     byte 0,1,0,1,0,1,0,1
    ARRAY_SIZE equ $ - inputB  

    ;The '$' acts as a place maker where you are currently in memory
    ;which at the end of the carryInNum array.
    ;The ending address of the carryInNum array minus the beginning
    ;address equals the total bytes of the carryInNum array
    ;which is stored in the ARRAY_SIZE constant.
    ;NOTE: there can be no other variables between the 
    ;declation of the ARRAY_SIZE constant and the declaration
    ;of the array you are trying to calculate the size of.

    ;You can add LFs to the strings below for proper output line spacing
    ;but do not change anything between the quotes "do not change".

    ;I will be using a comparison program to compare your output to mine and
    ;the spacing must match exactly.

    endingMsg           byte "Hit any key to exit!",0

    ;Change my name to your name
    titleMsg            byte "Program 4 by ",LF,0

    testingAdderMsg     byte " Testing Adder",0

    inputA_Msg           byte "   Input A: ",0
    inputB_Msg           byte "   Input B: ",0
    carryin_Msg          byte "  Carry in: ",0
    sum                  byte "       Sum: ",0
    carryout             byte " Carry Out: ",0

    dashes              byte LF," ------------",LF,0

;************************CODE SEGMENT****************************

.code

main PROC

    mov ecx, ARRAY_SIZE         ;ecx = ARRAY_SIZE
    mov esi, 0                  ;esi = 0

    mPrtStr titleMsg            ;print "Program 4 by"

AdderLoop:
    mPrtStr inputA_Msg          ;print "   Input A: "
    movzx   eax, inputA[esi]    ;eax = inputA[esi]
    INVOKE  WriteDec            ;write decimal stored in eax
    mov     al, LF              ;al = ASCII Line Feed
    INVOKE  WriteChar           ;write the character stored in al

    mPrtStr inputB_Msg          ;print "   Input B: "
    movzx   eax, inputB[esi]    ;eax = inputB[esi]
    INVOKE  WriteDec            ;write decimal stored in eax
    mov     al, LF              ;al = ASCII Line Feed
    INVOKE  WriteChar           ;write the character stored in al

    mPrtStr carryin_Msg         ;print "  Carry in: "
    movzx   eax, carryIn[esi]   ;eax = carryIn[esi]
    INVOKE  WriteDec            ;write decimal stored in eax
    mov     al, LF              ;al = ASCII Line Feed
    INVOKE  WriteChar           ;write the character stored in al

    call    adder               ;call the adder procedure

    mPrtStr dashes              ;print " ------------"

    mPrtStr sum                 ;print "       Sum: "
    mov     al, LF              ;al = ASCII Line Feed
    INVOKE  WriteChar           ;write the character stored in al

    mPrtStr carryout            ;print " Carry Out: "
    mov     al, LF              ;al = ASCII Line Feed
    INVOKE  WriteChar           ;write the character stored in al

    add     esi, 4              ;add 4 to esi to go to next element in the arrays
    loop    AdderLoop           ;ARRAY_SIZE--, if ARRAY_SIZE = 0 then end, else loop

    mPrtStr endingMsg           ;print "Hit any key to exit!"
    call    ReadChar            ;Pause program execution while user inputs a non-displayed char
    INVOKE  ExitProcess,0       ;Exit to dos: like C++ exit(0)

main ENDP

;IMPORTANT: Do not delete the function comment block below.
;           Every function should have a similar comment block
;           specifying what the function is about including:
;           - Description
;           - Input (Entry)
;           - Output (Exit)
;           - Registers used (REGS)

;************** Adder – Simulate a full Adder circuit  
;  Adder will simulate a full Adder circuit that will add together 
;  3 input bits and output a sum bit and a carry bit
;
;    Each input and output represents one bit.
;
;  Note: do not access the arrays in main directly in the Adder function. 
;        The data must be passed into this function via the required registers below.
;
;       ENTRY - EAX = input bit A 
;               EBX = input bit B
;               ECX = Cin (carry in bit)
;       EXIT  - EAX = sum bit
;               ECX = carry out bit
;       REGS  - EAX, EBX, ECX, ESI
;
;       For the inputs in the input columns you should get the 
;       outputs in the output columns below:
;
;        input                  output
;     eax  ebx   ecx   =      eax     ecx
;      A  + B +  Cin   =      Sum     Cout
;      0  + 0 +   0    =       0        0
;      0  + 1 +   0    =       1        0
;      1  + 0 +   0    =       1        0
;      1  + 1 +   0    =       0        1
;      0  + 0 +   1    =       1        0
;      0  + 1 +   1    =       0        1
;      1  + 0 +   1    =       0        1
;      1  + 1 +   1    =       1        1
;
;   Note: the Adder function does not do any output. 
;         All the output is done in the main function.
;
;Do not change the name of the Adder function.
;
;See additional specifications for the Adder function on the 
;class web site.
;
;You should use AND, OR and XOR to simulate the full adder circuit.
;
;You should save any registers whose values change in this function 
;using push and restore them with pop.
;
;The saving of the registers should
;be done at the top of the function and the restoring should be done at
;the bottom of the function.
;
;Note: do not save any registers that return a value (ecx and eax).
;
;Each line of the Adder function must be commented and you must use the 
;usual indentation and formating like in the main function.
;
;Don't forget the "ret" instruction at the end of the function
;
;Do not delete this comment block. Every function should have 
;a comment block before it describing the function. FA17


Adder proc

    push ecx                ;store ARRAY_SIZE for later

    movzx eax, inputA[esi]  ;eax = inputA[esi]
    movzx ebx, inputB[esi]  ;ebx = inputB[esi]
    movzx ecx, carryIn[esi] ;ecx = carryIn[esi]

    push eax                ;store inputA[esi] for later
    xor eax, ebx            ;eax = inputA[esi] XOR inputB[esi]
    push eax                ;store inputA[esi] XOR inputB[esi] for later
    xor eax, ecx            ;eax = (inputA[esi] XOR inputB[esi]) XOR carryIn[esi] (this is the sum)

    pop eax                 ;pop inputA[esi] XOR inputB[esi] into eax
    and ecx, eax            ;eax = (inputA[esi] XOR inputB[esi]) AND carryIn[esi]
    pop eax                 ;pop inputA[esi] into eax
    and eax, ebx            ;eax = inputA[esi] AND inputB[esi]
    or ecx, eax             ;ecx = ((inputA[esi] XOR inputB[esi]) AND carryIn[esi]) OR (inputA[esi] AND inputB[esi]) (this is the carry out)

    pop ecx                 ;pop ARRAY_SIZE into ecx

    ret                     ;return

Adder endp

END main

1 个答案:

答案 0 :(得分:5)

问题是loop只能向任一方向跳转最多128个字节。您的标签似乎离loop adderLoop无法触及。考虑将loop替换为dec ecx,然后替换为jnz adderLoop。有jnz的变体可以跳得更远,解决了这个问题。通常,我建议避免使用loop指令,因为它比可以替换它的dec ecx / jnz对慢。