assembly X86组件-结构点-未正确存储/返回?

ncecgwcz  于 2023-04-21  发布在  其他
关注(0)|答案(1)|浏览(124)

我刚开始处理结构点,这很令人困惑。
程序应该让用户输入5个值,将其保存在STRUC Point中,然后返回值。
“read_loop”读取用户输入并将其发送到readInt以转换为ASCII,然后当返回时,使用“mov [esi + Point.x],eax”和“mov [esi + Point.y],eax”保存,然后“read_loop应该在循环中打印出这些值。
这是预期的输出。

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

但是这是我得到的输出

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:

由于某种原因,它要么没有正确存储值,要么没有正确获取值?我已经尝试了几个小时来解决这个问题,我试图扰乱ALIGN,我看不出是什么原因导致值没有被返回。
下面是完整的代码

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

已尝试使用ALIGN,已检查以确保存储正确。

kkbh8khc

kkbh8khc1#

代码中的问题列表

; Debugging print statement
mov ecx, [esi + Point.x]
call printDec
  • printDec* 的参数进入EAX。这个错误发生了4次。
add esi, Point.size     ; Increment pointer to next structure in array
add esi, Point.size     ; Increment pointer to next structure in array

多余的第二个附加物。要删除。

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:

这两个跳跃都是多余的。

mov ecx, space
call printString

未给出所需的EDX参数。

jmp code_exit
code_exit:

一个多余的跳转,但罚款的情况下,未来增加的程序。

; Multiply eax by 10
lea ecx, [eax * 2 + eax] ; ecx = eax * 3
lea eax, [ecx * 2 + ecx] ; eax = ecx * 3 + ecx = eax * 9

你少了1倍!乘以10是简单的imul eax, 10

; Subtract ASCII '0'
sub byte [edi], '0'
add al, byte [edi]

进位需要在整个EAX中传播。
你可以写movzx edx, byte [edi]sub edx, '0'add eax, edx

由于pusha... popareadInt 不会返回EAX寄存器中的任何内容

.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

printDec 中,单独保存EDI不仅是多余的,而且是有害的。要删除。

相关问题