jes*_*ssa 1 x86 assembly emu8086
为了确定十六进制数是否为偶数,程序会将数字除以 2,余数应等于 0。如果不是,则它是奇数。最初,我的计划是有一个变量或寄存器,当十六进制被证明为偶数时,该变量或寄存器将递增。然后我就减去偶数的数量。到五即可得到奇数的数量。但由于我必须使用三个寄存器来保存被除数和除数 ( AX & BX),再加上另一个寄存器用于数组计数器 ( CX),所以我用完了寄存器来保存“偶数计数器”的值。
我修改了程序,使其仍然可以满足指令(见标题)。这次,程序将显示E偶数和O奇数的字符。我现在的问题是程序只能识别第二个数组项,这意味着 的值SI保持不变并且在第二个数组项之后不会增加。这使得程序的输出EOOOO而不是EOOOE.
SI我的问题是: 1.) 我将如何从内存中增加 的值并将其传递AX给除法 2.) 是否有可能使我的初始计划发挥作用?如果是,我可以使用什么寄存器来保存“偶数计数器”
这是代码:
.MODEL SMALL
READ MACRO MSG
MOV AH,0AH
LEA DX,MSG
INT 21H
ENDM
SET MACRO MSG
MOV AH,09H
LEA DX,MSG
INT 21H
ENDM
.DATA
CR EQU 0DH
LF EQU 0AH
ARR DW 100h,16Fh,191h,10Fh,120h
MSG1 DB CR,LF,"Array of 16 bit hexadecimals: 100h,16Fh,191h,10Fh,120h$"
MSG2 DB CR,LF,"E=EVEN O=ODD$"
NUMERALEVEN DB CR,LF,"E$"
NUMERALODD DB CR,LF,"O$"
COUNT EQU 5H
DATA ENDS
.CODE
ASSUME CS:CODE,DS:DATA
START:
MOV AX,DATA
MOV DS,AX
SET MSG1
SET MSG2
MOV SI,OFFSET ARR
MOV CL,COUNT
MOV AX,[SI]
MOV DX,0000
CHECK:
MOV DX,0000
MOV BH,00
MOV BL,02H ;divide by 2
DIV BX
CMP DX,0 ;checks if there is a remainder by comparing the remainder to 0
JE EVEN
JNE ODD
EVEN:
SET NUMERALEVEN
MOV DX,00
DEC CL
MOV AX,[SI+1]
MOV [SI],AX
CMP CL,0
JNZ CHECK
ODD:
SET NUMERALODD
DEC CL
MOV AX,00
MOV AX,[SI+1]
MOV [SI],AX
CMP CL,0
JNZ CHECK
CODE ENDS
END START
Run Code Online (Sandbox Code Playgroud)
这使得程序的输出
EOOOO而不是EOOOE.
您似乎并不完全了解代码中的以下指令的实际用途:
Run Code Online (Sandbox Code Playgroud)MOV AX,00 MOV AX,[SI+1] MOV [SI],AX
第一条指令没有用,因为第二条指令将覆盖 的值AX。
因为您的数组由 16 位值组成,并且 x86 CPU 使用字节寻址(与大多数但不是全部 CPU 一样),所以第二个值将存储在地址 处[SI+2],而不是存储在 处[SI+1]。
通过读取[SI+1],您可以读取一些(无意义)值,该值可以根据数组中的前两个数字计算出来。
使用最后一条指令覆盖数组中的第一个数字,这对我来说毫无意义。
您永远不会修改SI寄存器。如果不修改SI寄存器,您将永远无法读取数组后面的值!
所以你的程序的作用如下:
Initially, your array contains the values 100h,16Fh,...
You check the value 100h (if it is even or odd)
MOV AX,[SI+1] loads 6F01h into AX
MOV [SI],AX overwrites the first value in the array by 6F01h
You check the value 6F01h (if it is even or odd)
MOV AX,[SI+1] loads 6F6Fh into AX
MOV [SI],AX overwrites the first value in the array by 6F6Fh
You check the value 6F6Fh (if it is even or odd)
MOV AX,[SI+1] loads 6F6Fh into AX
MOV [SI],AX has no effect ...
... because the first element of the array is already 6F6Fh
MOV AX,[SI+1] loads 6F6Fh into AX
...
MOV AX,[SI+1] loads 6F6Fh into AX
...
MOV AX,[SI+1] loads 6F6Fh into AX
...
Run Code Online (Sandbox Code Playgroud)
所以你的程序第一次检查是100h偶数还是奇数。这就是你想要的。
第二次检查是6F01h偶数还是奇数。第三次、第四次、第五次……第十次……第一百次,它检查是6F6Fh偶数还是奇数。这可能是您不想要的。
为了确定十六进制数是否为偶数,程序会将数字除以 2,余数应等于 0。
如果您使用十进制数字(没有计算机)并且想要检查一个数字是否可以被十整除 - 您是否也会将该数字除以十并查看余数?
不。您会查看最后一位数字并检查它是否为零。
您可以在所有数字系统中执行此操作:
在三进制中,如果最后一位数字为零,则一个数可以被3整除;在十六进制系统中,如果最后一位数字为零,则它可以被 16 整除。在二进制系统中,如果最后一位数字(= 位)为零,则它可以被二整除。
您可以使用该TEST指令检查某个位是零还是一:
该指令TEST xxx, 1检查值的最后一位是否xxx为 0,如果是,则设置零标志(否则清除零标志)。这意味着如果该位为零,则JZ指令(与 相同JE)将跳转。如果该位为 1,则JNZ( ) 将跳转。JNE
因此,您可以将以下代码替换为指令TEST AX, 1:
MOV DX,0000
MOV BH,00
MOV BL,02
DIV BX
CMP DX,0
Run Code Online (Sandbox Code Playgroud)
您甚至可以使用TEST WORD [SI], 1直接检查数组中数字中的位,因此您甚至不需要使用MOV AX, [SI]将值加载到AX寄存器中。