I'm getting this error from:
loop AdderLoop
error A2075: jump destination too far : by 25 byte(s)
This is an adder program.
I'm still learning pop and push so maybe I'm not doing something right, but it seems like my variable ARRAY_SIZE isn't being stored correctly?
I push the register where ARRAY_SIZE is stored at the beginning of the procedure and pop it back at the end of the procedure.
.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
The problem is that loop can only jump by up to 128 bytes into either direction. It seems that your label is too far away for loop adderLoop to reach. Consider replacing loop with dec ecx and then jnz adderLoop. There is a variant of jnz that can jump much farther, solving this problem. Generally, I recommend to avoid using the loop instruction as it is slower than the dec ecx / jnz pair that can replace it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With