我对如何循环遍历结构体数组来获取输入并存储它,然后打印结构体中的所有输入感到非常困惑。我有这段代码,我可以在其中手动访问数组的索引,并且它确实有效。
.model small
.stack 100h
.data
Person struc
name db 10 DUP(0)
password db 10 DUP(0)
Person ends
people Person 10 DUP(<>)
prompt db 'Enter your name: ', 0
prompt2 db 13, 10, 'Enter password: ', 0
res db 13, 10, 'Your name is: ', 0
res2 db 13, 10, 'Your password is: ', 0
.code
include io.mac
main proc
mov ax, @data
mov ds, ax
mov si, 0
; First person (index 0)
PutStr prompt
GetStr people[0].name
PutStr prompt2
GetStr people[0].password
PutCh 0Ah
; Second person (index 1)
PutStr prompt
GetStr people[20].name
PutStr prompt2
GetStr people[20].password
PutCh 0Ah
; Third person (index 2)
PutStr prompt
GetStr people[40].name
PutStr prompt2
GetStr people[40].password
PutCh 0Ah
; Print first person's info (index 0)
PutStr res
PutStr people[0].name
PutStr res2
PutStr people[0].password
PutCh 0Ah
; Print second person's info (index 1)
PutStr res
PutStr people[20].name
PutStr res2
PutStr people[20].password
PutCh 0Ah
; Print third person's info (index 2)
PutStr res
PutStr people[40].name
PutStr res2
PutStr people[40].password
PutCh 0Ah
mov ax, 4C00h
int 21h
main endp
end main
但问题是我不想手动输入所有这些,所以我尝试做一个循环以使事情变得更容易......但事实并非如此。这是我的代码:
.model small
.stack 100h
.data
Person struc
name db 10 DUP(0)
password db 10 DUP(0)
Person ends
people Person 10 DUP(<>)
prompt db 'Enter your name: ', 0
prompt2 db 13, 10, 'Enter password: ', 0
res db 13, 10, 'Your name is: ', 0
res2 db 13, 10, 'Your password is: ', 0
.code
include io.mac
main proc
mov ax, @data
mov ds, ax
mov cx, 3
mov si, 0
loop_input:
PutStr prompt
GetStr people[si].name
PutStr prompt2
GetStr people[si].password
PutCh 0Ah
add si, size Person ; size = 20
loop loop_input
mov cx, 3
mov si, 0
loop_output:
PutStr res
PutStr people[si].name
PutStr res2
PutStr people[si].password
PutCh 0Ah
add si, size Person ; size = 20
loop loop_output
mov ax, 4C00h
int 21h
main endp
end main
这是我手动访问索引时的输出。
这是我使用循环时的输出。 在此输入图片描述
我在这两个代码中看到的唯一区别是 si 寄存器。在第一个代码中,您没有使用它,您使用值来访问内存地址。
我不知道 PutStr 和 GetStr 是如何实现的,可能在 io.mac 中,但似乎它们正在更改 si 寄存器.
在 io.mac 中,GetStr 和 PutStr 宏定义为:
GetStr MACRO string1, buffer_size, extra IFB <string1> %OUT ERROR: Missing string parameter in GetStr macro. EXITM ENDIF push CX ;; CX is used for buffer size IFB <buffer_size> %OUT WARNING: Missing string length parameter in GetStr macro. %OUT Maximum string length of 80 is used. mov CX,81 ;; 80 + 1 for CR ELSE mov CX,buffer_size ENDIF IFNB <extra> %OUT WARNING: Redundant parameters in GetStr macro - ignored. ENDIF push AX mov AX,OFFSET string1 call proc_GetStr pop AX pop CX ENDM
PutStr MACRO string, extra IFB <string> %OUT ERROR: Missing string parameter in PutStr macro. EXITM ENDIF IFNB <extra> %OUT WARNING: Redundant parameters in PutStr macro - ignored. ENDIF push AX mov AX,OFFSET string call proc_PutStr pop AX ENDM
虽然我还没有看到 proc_GetStr 和 proc_PutStr 中的内容,但看到甚至 AX 寄存器也被保留,我认为可以安全地假设所有寄存器最终都被保留。
让我担心的是他们在
mov AX,OFFSET string1
和 mov AX,OFFSET string
中使用了 OFFSET。这需要一个在汇编时已知的操作数。你的 people[0].name
没问题,但你的 people[si].name
不行,因为在组装时不知道 SI 寄存器将包含什么。如果使用这些宏 lea AX, string1
和 lea AX, string
你的程序可能会工作。
就个人而言,我会编辑 io.mac 文本文件并以这种方式解决它。
GetStr people[si].name PutStr prompt2 GetStr people[si].password
您没有为 GetStr 指定可选的第二个宏参数。因为它默认为 81 并且考虑到您的字段仅限于 10 个字节,所以这样写会更安全:
GetStr people[si].name, 10
PutStr prompt2
GetStr people[si].password, 10