【问题标题】:8086 assembly language program to find number of odd and even numbers in an array of 16-bit hexadecimal numbers8086 汇编语言程序在 16 位十六进制数数组中查找奇数和偶数的数量
【发布时间】:2021-05-12 05:25:19
【问题描述】:

为了确定十六进制数是否为偶数,程序会将数字除以 2,余数应为零。如果不是,那么它是一个奇数。最初,我的计划是我有一个变量或寄存器,当十六进制被证明是偶数时它会增加。然后我会减去偶数的数量。到五得到奇数的数量。但由于我必须使用三个寄存器来保存被除数和除数 (AX & BX),再加上另一个用于数组计数器 (CX),所以我用完了寄存器来保存“偶数计数器”的值。

我修改了程序,使它仍然可以满足指令(见标题)。这一次,程序将显示字符E 表示偶数,O 表示奇数。我现在的问题是程序最多只能识别第二个数组项,这意味着 SI 的值保持不变并且在第二个数组项之后不会增加。这使得程序的输出为EOOOO 而不是EOOOE

我的问题是: 1.) 我将如何从内存中增加SI 的值并将其传递给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 

【问题讨论】:

  • 只需在每次迭代结束时将 2 添加到 SI - 无需移动元素。请注意,它应该是 2,而不是 1,因为您正在处理单词。此外,不需要DIV。您可以通过使用TEST 指令测试最低有效位来检查数字是奇数还是偶数。
  • 计算机中的数字以二进制形式存储;这就是左移乘以 2 的原因。您只在源代码中使用十六进制;汇编器将 ASCII 十六进制源代码转换为二进制整数,就像您将它们写成十进制一样,例如 256 而不是 100h。只是我的一个术语,但我认为理解这一点很重要。

标签: assembly x86 emu8086


【解决方案1】:

这使得程序的输出为EOOOO 而不是EOOOE

您似乎并不完全了解您的代码中的以下指令实际上是做什么的:

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
   ...

所以你的程序第一次检查100h 是偶数还是奇数。这就是你想要的。

第二次检查6F01h 是偶数还是奇数。第三、第四、第五……第十……一百次,它检查6F6Fh 是偶数还是奇数。这可能是你不想要的。

为了确定十六进制数是否为偶数,程序会将数字除以 2,余数应为零。

如果您使用十进制数(没有计算机)并想检查一个数字是否能被十整除 - 您是否也将这个数字除以十并查看余数?

没有。您将查看最后一位数字并检查它是否为零。

您可以在所有数字系统中执行此操作:

在三进制系统中,如果最后一位数字为零,则数字可以被 3 整除;在十六进制系统中,如果最后一位为零,则可以被 16 整除。在二进制系统中,如果最后一位(= 位)为零,则可以被 2 整除。

您可以使用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

您甚至可以使用TEST WORD [SI], 1 直接检查数组中某个数字中的位,因此您甚至不需要使用MOV AX, [SI] 将值加载到AX 寄存器中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-24
    • 2013-03-05
    • 2011-12-08
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多