I just started working with structure points and it's quite confusing.
The Program is supposed to let a user enter 5 values, save it in the STRUC Point and then return what the values are.
The "read_loop" reads the users inputs and sends it to readInt to be translated to ASCII, then when returned it's saved using "mov [esi + Point.x], eax" and "mov [esi + Point.y], eax" then the "read_loop should print back out those values in a loop.
This is the expected output.
Enter x and y values for point:
53
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Point values:
53
6
Point values:
3
6
Point values:
3
6
Point values:
3
6
Point values:
3
6
However this is the output I'm getting
Enter x and y values for point:
53
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Enter x and y values for point:
3
6
Point values:
Point values:
Point values:
Point values:
Point values:
For some reason it's either not storing the values correctly, or isn't grabbing the values correctly? I've been trying to troubleshoot it for hours, I tried messing with ALIGN and I can't see what's causing the values to not be returned.
Here is the complete code
STRUC Point ; define point structure
.x: RESD 1 ;reserve 4 bytes for x coordinate
.y: RESD 1 ;reserve 4 bytes for y coordinate
.size:
ENDSTRUC
section .data
enter_msg db 'Enter x and y values for point: ',10, 0
enter_msg_len: equ $-enter_msg
space db ' ', 0
output_msg db 'Point values: ', 10, 0
output_msg_len: equ $-output_msg
section .bss
PtArr: RESB Point.size*5 ; reserve place for 5 structures
ArrCount: EQU ($-PtArr) / Point.size ; Should be 5 structures
section .text
global _start
_start:
push ebp ; Save ebp for whoever called main function (OS or other program)
mov ebp, esp ; Create our new stack frame
; Initialize esi register to point to the start of PtArr
lea esi, [PtArr]
mov ebx, 5 ; Initialize loop counter with the desired number of iterations
read_loop:
mov ecx, enter_msg ; Print message #1
mov edx, enter_msg_len
call printString
; Read x value
call readInt
mov [esi + Point.x], eax
; Debugging print statement
mov ecx, [esi + Point.x]
call printDec
call printNewLine
; Read y value
call readInt
mov [esi + Point.y], eax
; Debugging print statement
mov ecx, [esi + Point.y]
call printDec
call printNewLine
add esi, Point.size ; Increment pointer to next structure in array
add esi, Point.size ; Increment pointer to next structure in array
dec ebx ; Decrement loop counter
jnz read_loop ; Jump to beginning of loop if counter is not zero
jmp prepare_print_loop ; Jump to prepare_print_loop to reset esi and then jump to print_loop
jmp prepare_print_loop ; Jump to prepare_print_loop to reset esi and then jump to print_loop
prepare_print_loop:
; Reset esi to point to the start of PtArr
lea esi, [PtArr]
; Initialize loop counter with the desired number of iterations (5 in this case)
sub ebx, ebx
mov ebx, 5
; Debugging print loop
mov ecx, output_msg ; Print message #2
mov edx, output_msg_len
call printString
mov ecx, [esi + Point.x]
call printDec
mov ecx, space
call printString
mov ecx, [esi + Point.y]
call printDec
call printNewLine
print_loop:
; Display output message
mov ecx, output_msg ; Print message #2
mov edx, output_msg_len
call printString
; Save the value of esi
push esi
; Print x value
mov eax, [esi + Point.x]
call printDec
; Print space
mov ecx, space
mov edx, 1
call printString
; Print y value
mov eax, [esi + Point.y]
call printDec
; Print newline
call printNewLine
; Restore the value of esi
pop esi
; Increment to the next structure
add esi, Point.size
dec ebx
jnz print_loop
jmp code_exit
code_exit:
; Exit the program
mov eax, 1
xor ebx, ebx
int 0x80
readInt:
; Save register values of the called function
pusha
; Allocate buffer for input
sub esp, 16
; Read input from the user (system call 3)
mov eax, 3
xor ebx, ebx
lea ecx, [esp]
mov edx, 15
int 0x80
; Convert string to integer
xor eax, eax
xor edi, edi
lea edi, [esp]
.str_to_int_loop:
cmp byte [edi], 10 ; Check for newline character
je .str_to_int_done
; Multiply eax by 10
lea ecx, [eax * 2 + eax] ; ecx = eax * 3
lea eax, [ecx * 2 + ecx] ; eax = ecx * 3 + ecx = eax * 9
; Subtract ASCII '0'
sub byte [edi], '0'
add al, byte [edi]
inc edi
jmp .str_to_int_loop
.str_to_int_done:
; Restore stack and register values
add esp, 16
popa
ret
printString:
;Save register values of called function
pusha
mov eax, 4 ;use 'write' system call = 4
mov ebx, 1 ;file descriptor 1 = STDOUT
int 80h ;call the kernel
;restore the old register values of the called function
popa
ret
; Add printNewLine function
section .data
nl db "", 10
section .text
printNewLine:
;save register values of the called function
pusha
mov ecx, nl
mov edx, 1
mov eax, 4
mov ebx, 1
int 0x80
;restore the old register values of the called function
popa
ret
printDec:
section .bss
decstr resb 10;
ct1 resd 1
section .text
pusha ;save all registers
; Save the value of edi
push edi
mov dword[ct1], 0 ; assume initially 0
mov edi, decstr ;edi points to dec-string in memory
add edi, 9 ;moved to the last element of string
xor edx, edx
whileNotZero:
mov ebx, 10 ;get ready to divide by 10
div ebx ;divide by 10
add edx,'0' ; convert to ascii char
mov byte[edi], dl ; put it in string
dec edi ;move to next char in string
inc dword[ct1]
xor edx, edx ;clear edx
cmp eax, 0 ;is remainder 0
jne whileNotZero ; keep looping
; Restore the value of edi
pop edi
inc edi ; conversion finish
mov ecx, edi
mov edx, [ct1]
mov eax, 4
mov ebx, 1
int 0x80
popa ;restore registers
ret
Tried using ALIGN, checked to make sure it's storing properly.
; Debugging print statement mov ecx, [esi + Point.x] call printDec
The argument to printDec goes in EAX. This mis-hap occurs 4 times.
add esi, Point.size ; Increment pointer to next structure in array add esi, Point.size ; Increment pointer to next structure in array
A redundant second addition. To be removed.
jmp prepare_print_loop ; Jump to prepare_print_loop to reset esi and then jump to print_loop jmp prepare_print_loop ; Jump to prepare_print_loop to reset esi and then jump to print_loop prepare_print_loop:
Both these jumps are redundant.
mov ecx, space call printString
The required EDX argument was not given.
jmp code_exit code_exit:
A redundant jump but fine in case of future additions to the program.
; Multiply eax by 10 lea ecx, [eax * 2 + eax] ; ecx = eax * 3 lea eax, [ecx * 2 + ecx] ; eax = ecx * 3 + ecx = eax * 9
You're 1 time short here! Times 10 is simple imul eax, 10
.
; Subtract ASCII '0' sub byte [edi], '0' add al, byte [edi]
The carry needs to propagate through the whole EAX.
You could write movzx edx, byte [edi]
sub edx, '0'
add eax, edx
.
Because of pusha
... popa
, readInt isn't returning anything in the EAX register.
.str_to_int_done:
; Restore stack and register values
add esp, 16
mov [esp+28], eax ; Return EAX through overwriting pushad.EAX
popa
ret
; Save the value of edi push edi ... ; Restore the value of edi pop edi
In printDec, the separate preserving of EDI is not only redundant but also harmful. To be removed.