【问题标题】:8086 Assembler compare two operands without CMP8086 汇编器在没有 CMP 的情况下比较两个操作数
【发布时间】:2015-05-22 17:47:00
【问题描述】:

问题:

在数据段中,我有两个数组 A,B (DW),大小为 1<N<20,其中一些 数字(代码仅在数组长度小于 20 时运行),代码需要运行 在两个数组中并检查数组相同索引中的数字是否相等, 将它们推入堆叠。注意:需要在没有 CMP 的情况下执行此操作。

示例 A:

A DW 1234,35235,1234,5678
B DW 4532,32735,5678,1234
N=4

堆栈将为空

示例 B:

A DW 4532,35235,1234,5678 
B DW 4532,32735,1234,1234
N=4

数字 4532 和 1234 入栈

我的代码:

DATA SEGMENT
    A DW 4535
    B DW 4535
    SIZEA = OFFSET B /2
    SIZEB = ($-B)/2
DATA ENDS  

CODE SEGMENT
    ASSUME CS:CODE, DS:DATA
    START:   
    MOV AX,DATA
    MOV DS,AX   
    MOV SP,100h      
    MOV CX,SIZEB ;how times loop run
    MOV DX,SIZEA ;to compare sizes of arrays
    TEST CX,19   ;if size of array B above 19 numbers jump to end
    JNP END
    TEST DX,19   ;if size of array A above 19 numbers jump to end
    JNP END
    XOR DX,CX    ;if arrays size not equal jump to end
    JNZ END


    MOV SI,0    ;index of array
CHECK: 
    MOV AX,A(SI)
    MOV BX, B(SI)
    SUB AX,BX  ;if same numbers zf=1, jump to find
    JZ FIND
    ADD SI,2   ;goes to next index (2 because DW)
    LOOP CHECK ;checking next index
    JMP END    ;when cx = 1 jump to end
FIND: 
    PUSH BX    ;pushing to stack equal number
    ADD SI,2
    LOOP CHECK 
END:
CODE ENDS 
END START 

除长度 19,16,14,13,10,9,6,5,2,1 外,此方法有效

【问题讨论】:

  • 我想知道为什么你不能使用 CMP。无论如何,为什么不从另一个中减去一个并测试为零呢? (不过,您可能需要稍微调整一下负数)
  • 这是汇编程序考试的示例问题,我必须在下周做。有问题写道:编写代码而不使用 CMP =)
  • 您使用TEST 的方式与您的评论“如果大小超过 19”不匹配。
  • Ruud,我不知道如何通过另一种方式检查,我同意,TEST 不是解决方案,需要其他东西....但测试它的一半工作 =)
  • 避免cmp 的简单方法是将其替换为pushsub &poppush & pop 如果目标的更改值无关紧要,可以省略。如果需要,更改可以很容易地自动化。 stackoverflow.com/questions/15098073/…

标签: assembly x86-16


【解决方案1】:
TEST CX,19   ;if size of array B above 19 numbers jump to end
JNP END
TEST DX,19   ;if size of array A above 19 numbers jump to end
JNP END
XOR DX,CX    ;if arrays size not equal jump to end
JNZ END

为什么不使用 TEST 和 SUB 来测试这些条件?最初的问题是 1 。示例程序已经违反了这个条件。它使用 N=1。

sub dx,cx
jnz end     ;exit different sized arrays
test cx,cx
jle end     ;exit [-32768,0]
dec cx
jz end      ;exit 1
sub cx,19
jns end     ;exit [20,32767]
mov cx,SIZEB

【讨论】:

    【解决方案2】:
    DATA SEGMENT
        A DW 4535
        B DW 4535
        B_A = OFFSET B - OFFSET A
        SIZEA = B_A /2
        SIZEB = ($-B)/2
    DATA ENDS
    
    CODE SEGMENT
        ASSUME CS:CODE, DS:DATA
    START:
        MOV AX,DATA
        MOV DS,AX
        MOV SP,100h
        MOV CX,SIZEB    ;how times loop run
    #IFDEF DontUseAssDir
        MOV DX,SIZEA    ;to compare sizes of arrays
        XOR DX,CX       ;if arrays size not equal jump to end
        JNZ END
        MOV AX,19
        SUB AX,CX       ;if size of array B above 19 numbers jump to end
        JC END
        SUB AX,18       ;if size of array B below 2 numbers jump to end
        JC END
    #ELSEIF NOT SIZEA = SIZEB
    # ERR A and B have different sizes
    #ELSEIF 19 < SIZEA
    # ERR A and B are larger than 19 elements
    #ELSEIF SIZEA < 2
    # ERR A and B are smaller than 2 elements
    #ENDIF
    
        MOV SI,OFFSET A ;address of array
        CLD
    #IF CPU=8086 OR CPU=80186
        ALIGN 2        ;align address for loop if 8086, don't bother for 8088
    #ENDIF
    CHECK:
        MOV BX, B_A(SI) ;get B(SI)
        LODSW           ;get A(SI) and ADD SI,2
        SUB AX,BX       ;if same numbers zf=1, don't loop
        LOOPNE CHECK    ;checking next index unless equal
    
        JNE END         ;job done, if not equal
        PUSH BX         ;pushing to stack equal number
        JCXZ END        ;don't loop if cx=0
        JMP CHECK       ;else next index
    END:
        CODE ENDS
    END START
    

    如果边界是固定的,请使用汇编器检查它们。 如果它们的大小应该相同,则无需检查 A 和 B 的边界。 由于未检查 SI,因此最好将地址放在 SI 中,并将 A 和 B 地址之间的差异用于其他 MOV。

    【讨论】:

      猜你喜欢
      • 2014-04-04
      • 1970-01-01
      • 2011-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多