我目前正在x86程序集中编写一个简单程序,它将数据存储在任意内存地址并以十六进制形式打印到终端。它正在NASM 2.12.02中组装,我用bochs 2.6.8运行生成的垃圾箱。我编写了一个名为print_hex.asm
的例程,它使用db
来定义ascii字符的索引,如下所示。
ascii_table: db "0123456789ABCDEF"
组装完整程序并运行结果时,同一行
(an increasing number)i[CPU0 ] MOV_EwSw: using of nonexisting segment register 7
重复打印到终端,前面是一个不断增加的数字。如果我将线路更改为
,会有什么奇怪的 ascii_table: db "0123456789ABC"
通过简单地省略字符串的最后三个字母,它工作得很好(尽管组装的程序在尝试转换D,E或F的十六进制值时会出现运行时错误)
这里发生了什么?我不允许连续声明这么多数据吗? NASM对我不好意思吗?
编辑:请参阅下面的完整源代码。请注意,它仍在进行中,可能在其他地方出现逻辑错误。
print_hex: ; prints the value stored at bx in hex
pusha ; push all the local registers to the stack
ascii_table: ; define a table to store ascii characters for conversion
db "0123456789ABCDEF"
mov ah, 0x0e ; move 0x0e to the high byte of ax in preparation for a teletype interrupt
mov al, "0" ; move the ascii char 0 to the lower byte of ax
int 0x10 ; perform a teletype interrupt
mov al, "x" ; move the ascii char x to the lower byte of ax
int 0x10 ; perfrom a teletype interrupt
mov dx, 0 ; move 0 to dx in preparation for the loop
mov cx, 0 ; zero out cx
hex_print_loop_start:
mov cl, bl ; move bl to cl to isolate the lowest nybble of bx
add cl, ascii_table ; set the table offset with cx
mov al, cl ; get the value at the offset index of the table and store it in al for printing
int 0x10 ; perform a teletype interrupt
inc dx ; increment dx by one
shr bx, 1 ; shift bx right in preparation for reading the next character
cmp dx, byte 0x04 ; check if the loop has been performed 4 times
jl hex_print_loop_start ; if it hasn't been performed 4 times, jump to the beginning of the loop
popa ; restore local registers
ret ; return
答案 0 :(得分:7)
您必须将字符串数据移出代码,因为CPU在执行pusha
指令后将执行字符串作为指令。您的字符串被解释为以下代码:
'01' 30 31 XOR BYTE PTR [BX+DI],DH
'23' 32 33 XOR DH,BYTE PTR [BP+DI]
'45' 34 35 XOR AL,35H
'67' 36:37 SS:AAA ; Superfluous prefix
'89' 38 39 CMP BYTE PTR [BX+DI],BH
'A' 41 INC CX
'B' 42 INC DX
'C' 43 INC BX
'D' 44 INC SP
'E' 45 INC BP
'F' 46 INC SI
只要这些指令非常随机,就会产生随机行为。另请注意,堆栈指针已被修改,因此在程序退出时会出现更多混乱。