DOSBox 调试程序集
DOSBox Debug Assembly
我是 运行 DOSBox,使用调试实用程序构建汇编代码。我只是想弄清楚如何读取字符串。到目前为止我有这个。
-n test.com
-a
072A:0100 db 15
072A:0101 db 16
072A:0102 mov dx, 100
072A:0105 mov ah, 0A
072A:0107 int 21
072A:0109 int 20
-rcx 15
-w
-q
所以我可以从缓冲区中读入一个不超过 15 个字符的字符串。当我读入字符串时,它被放在哪里?我想尝试打印字符串。
您示例中的代码有 2 个问题。
您不想将原始数据放在偏移量 100 处,因为 DOS 将从该地址开始执行。因此,从偏移量 102 开始的代码将无法正确执行,因为它将 assemble 到 "ADC AX,BA16" 指令,该指令从 "mov dx,100" 指令中窃取 BA 字节,其余指令将被误解。
如果您没有遇到问题 #1,那么第二个问题是输入字符将从偏移量 102 开始覆盖您的代码(因为缓冲区 100 处的前两个字节已保留)。如果您可以让代码执行,这可能不是您想要的。 ;)
您不想在偏移量 100 处定义任何数据,因为这是 .COM 程序的入口点。处理此问题的一种简单方法是在代码之后定义数据。当使用调试之类的东西时,您必须直接指定内存位置而不使用标签,必须考虑 assembled 操作数的大小。
一种方法是 assemble 您的代码从地址 100 开始,并为您的字符串和缓冲区地址使用占位符;然后在定义数据后修复这些说明。
这是您修改后的样本:
注意:我忍不住在字符串输入函数之前添加了一个输出提示
-n test2.com
-a
0100: mov dx,100 ;100 is a placeholder for the address of output prompt
0103: mov ah,9
0105: int 21 ;output prompt
0107: mov dx,100 ;100 is a placeholder for the address of the input buffer
010A: mov ah,0a
010C: int 21 ;read user input
010E: int 20
0110: db 48 ;"H"
0111: db 65 ;"e"
0112: db 6c ;"l"
0113: db 6c ;"l"
0114: db 6f ;"o"
0115: db 3a ;":"
0116: db 20 ;<space>
0117: db 24 ;"$" / DOS strings terminated by dollar sign
0118: db 0f ;buffer member: hold 15 chars
0119: db 00 ;buffer member: character input count stored here
;the remainder of the .COM memory segment can be used to store the data
; starting at address 11A
;now that we know where our data fits, lets plug the addresses in
-a 100
0100: mov dx,110 ;address of "H" in prompt string
-a 107
0100: mov dx,118 ;address of input buffer with first two bytes reserved (see above)
;max length to read and characters read
-rcx
CX 0000
:1a
-w
Writing 001A bytes
;lets run the program
-g
Hello: <lets assume you type "cat" followed by RETURN>
Program terminated normally
;now look at the 2nd byte in the buffer for the number of characters typed
; along with the character data entered
-d 118 11e
0110 0F 03 63 61 74 0D 0D ..cat..
我认为一旦定义了 max input chars 成员,您就不必担心为缓冲区保留 space;由于缓冲区位于程序末尾,您可以访问 64k 段的剩余部分作为缓冲区 space。 (64k 减去 0x11b 字节的代码和环境space)。
编辑 2016/09/11
这是一个修订版(带有解释),可以解决您关于输出用户输入内容的问题:
0100 MOV DX,0140
0103 MOV AH,09
0105 INT 21 ;output prompt
0107 MOV DX,014B
010A MOV AH,0A
010C INT 21 ;read user input
010E MOV DX,0148
0111 MOV AH,09
0113 INT 21 ;output CRLF
0115 MOV DI,[014C] ;load DI with value of characters read
0119 AND DI,00FF ; MOV above read WORD, but we only want lower byte
011D LEA DI,[DI+014D] ;point DI to end of input string
0121 MOV AL,24 ;load DOS terminator char "$" in AL
0123 STOSB ;write it to end input string
0124 MOV DX,014D
0127 MOV AH,09
0129 INT 21 ;print the input string
012B INT 20 ;exit program
;I inserted NOPS until address 0140 so I would have room to insert code without my
; data offsets changing
0140 DB 48 ;"Hello: $" prompt begin
0141 DB 65
0142 DB 6C
0143 DB 6C
0144 DB 6F
0145 DB 3A
0146 DB 20
0147 DB 24
0148 DB 0D ;CRLF$ sequence begin
0149 DB 0A
014A DB 24
014B DB 20 ;Buffer begin (32 bytes max length)
014C DB 00
有多种方法可以实现相同的结果,例如将用户输入计数加载到 CX 寄存器,并使用 LOOP 指令使用适当的 DOS 函数打印每个字符。祝你好运!
我是 运行 DOSBox,使用调试实用程序构建汇编代码。我只是想弄清楚如何读取字符串。到目前为止我有这个。
-n test.com
-a
072A:0100 db 15
072A:0101 db 16
072A:0102 mov dx, 100
072A:0105 mov ah, 0A
072A:0107 int 21
072A:0109 int 20
-rcx 15
-w
-q
所以我可以从缓冲区中读入一个不超过 15 个字符的字符串。当我读入字符串时,它被放在哪里?我想尝试打印字符串。
您示例中的代码有 2 个问题。
您不想将原始数据放在偏移量 100 处,因为 DOS 将从该地址开始执行。因此,从偏移量 102 开始的代码将无法正确执行,因为它将 assemble 到 "ADC AX,BA16" 指令,该指令从 "mov dx,100" 指令中窃取 BA 字节,其余指令将被误解。
如果您没有遇到问题 #1,那么第二个问题是输入字符将从偏移量 102 开始覆盖您的代码(因为缓冲区 100 处的前两个字节已保留)。如果您可以让代码执行,这可能不是您想要的。 ;)
您不想在偏移量 100 处定义任何数据,因为这是 .COM 程序的入口点。处理此问题的一种简单方法是在代码之后定义数据。当使用调试之类的东西时,您必须直接指定内存位置而不使用标签,必须考虑 assembled 操作数的大小。
一种方法是 assemble 您的代码从地址 100 开始,并为您的字符串和缓冲区地址使用占位符;然后在定义数据后修复这些说明。
这是您修改后的样本:
注意:我忍不住在字符串输入函数之前添加了一个输出提示
-n test2.com
-a
0100: mov dx,100 ;100 is a placeholder for the address of output prompt
0103: mov ah,9
0105: int 21 ;output prompt
0107: mov dx,100 ;100 is a placeholder for the address of the input buffer
010A: mov ah,0a
010C: int 21 ;read user input
010E: int 20
0110: db 48 ;"H"
0111: db 65 ;"e"
0112: db 6c ;"l"
0113: db 6c ;"l"
0114: db 6f ;"o"
0115: db 3a ;":"
0116: db 20 ;<space>
0117: db 24 ;"$" / DOS strings terminated by dollar sign
0118: db 0f ;buffer member: hold 15 chars
0119: db 00 ;buffer member: character input count stored here
;the remainder of the .COM memory segment can be used to store the data
; starting at address 11A
;now that we know where our data fits, lets plug the addresses in
-a 100
0100: mov dx,110 ;address of "H" in prompt string
-a 107
0100: mov dx,118 ;address of input buffer with first two bytes reserved (see above)
;max length to read and characters read
-rcx
CX 0000
:1a
-w
Writing 001A bytes
;lets run the program
-g
Hello: <lets assume you type "cat" followed by RETURN>
Program terminated normally
;now look at the 2nd byte in the buffer for the number of characters typed
; along with the character data entered
-d 118 11e
0110 0F 03 63 61 74 0D 0D ..cat..
我认为一旦定义了 max input chars 成员,您就不必担心为缓冲区保留 space;由于缓冲区位于程序末尾,您可以访问 64k 段的剩余部分作为缓冲区 space。 (64k 减去 0x11b 字节的代码和环境space)。
编辑 2016/09/11
这是一个修订版(带有解释),可以解决您关于输出用户输入内容的问题:
0100 MOV DX,0140
0103 MOV AH,09
0105 INT 21 ;output prompt
0107 MOV DX,014B
010A MOV AH,0A
010C INT 21 ;read user input
010E MOV DX,0148
0111 MOV AH,09
0113 INT 21 ;output CRLF
0115 MOV DI,[014C] ;load DI with value of characters read
0119 AND DI,00FF ; MOV above read WORD, but we only want lower byte
011D LEA DI,[DI+014D] ;point DI to end of input string
0121 MOV AL,24 ;load DOS terminator char "$" in AL
0123 STOSB ;write it to end input string
0124 MOV DX,014D
0127 MOV AH,09
0129 INT 21 ;print the input string
012B INT 20 ;exit program
;I inserted NOPS until address 0140 so I would have room to insert code without my
; data offsets changing
0140 DB 48 ;"Hello: $" prompt begin
0141 DB 65
0142 DB 6C
0143 DB 6C
0144 DB 6F
0145 DB 3A
0146 DB 20
0147 DB 24
0148 DB 0D ;CRLF$ sequence begin
0149 DB 0A
014A DB 24
014B DB 20 ;Buffer begin (32 bytes max length)
014C DB 00
有多种方法可以实现相同的结果,例如将用户输入计数加载到 CX 寄存器,并使用 LOOP 指令使用适当的 DOS 函数打印每个字符。祝你好运!