肖-肖 发表于 2021-5-25 15:31:37

还是一个有问题的程序,请指点一下

本帖最后由 肖-肖 于 2021-5-25 15:37 编辑

题目是:
       实现:在270H开始的内存单元中存放了16个8位带符号数,找出其中最大和最小的数分别存入以280H和282H为首地址的内存单元
我的代码是:
DATAS SEGMENT
    ;此处输入数据段代码
    org 0270H
    n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,87H        
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
    ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    ;此处输入代码段代码
    mov si,0270H
    mov al,
    mov bl,al
    mov cl,0FH
ks:inc si
    dec cl
    jz over
    cmp al,
    JLE next
    mov al,
next:cmp bl,
        JG ks
        mov bl,
        jmp ks
over:mov si,0280H
        mov ,bl
        add si,2
        mov ,al        
    MOV AH,4CH
    INT 21H
CODES ENDS
    END START
我运行出来的结果是:

我觉得如果看成是带符号数得话,88H不才是最小的那个负数吗? 我哪里不对?请指点一下,详细点(最好给个代码),我比较笨,谢谢了

上善若水··· 发表于 2021-5-25 16:12:32



https://www.aldeid.com/wiki/X86-assembly/Instructions/cmp

肖-肖 发表于 2021-5-25 16:19:33

上善若水··· 发表于 2021-5-25 16:12
https://www.aldeid.com/wiki/X86-assembly/Instructions/cmp

哦哦 您的意思是说:这么cmp相当于减,这个我知道,但是后边的那个表格说它之影响:ZF和CF对吗?

上善若水··· 发表于 2021-5-25 16:21:24

肖-肖 发表于 2021-5-25 16:19
哦哦 您的意思是说:这么cmp相当于减,这个我知道,但是后边的那个表格说它之影响:ZF和CF对吗?

恩,是的

肖-肖 发表于 2021-5-25 16:22:05

上善若水··· 发表于 2021-5-25 16:21
恩,是的

不对吧
我查了下资料
资料如下
CMP比较指令使用寄存器Rn的值减去operand2的值,根据操作的结果影响新CPSR中相应的条件标志位,以便后面的指令根据相应的条件标志来判断是否执行。CMP指令与SUBS指令的区别在于CMP指令不保存运算结果。在进行两个数据大小判断时,常用CMP指令及相应的条件码来操作。

CMP指令的格式为CMP op1 op2用到的标志位有CF,ZF,OF,SF四个,对于两个无符号数的情况,两数相减不可能溢出了,看CF和ZF标志位就可以,如果ZF为1,说明结果是0,那不用说,两数相等了(有符号数也是这样),如果ZF为0,则如果CF为1,表示有借位,op1<op2,否则op1>op2。

对于有符号数,就要看符号标志位SF和溢出标志位OF了,如果是两个同号的数,两数相减也是不可能溢出的,OF一定为0,此时,如果SF为1,则表示op1<op2,否则op1>op2,如果是两个异号的数相减,不溢出的情况跟上面的一样(OF==0,SF==1?op1<op2:op1>op2)。

肖-肖 发表于 2021-5-25 16:23:36

肖-肖 发表于 2021-5-25 16:22
不对吧
我查了下资料
资料如下


我用的JLE不是判断带符号数的大小吗?
省的去判断OF和SF了,挺麻烦的

上善若水··· 发表于 2021-5-25 16:45:01

不好意思,上面的回复有点出入,刚翻了下 INTEL 手册,内容如下。





人造人 发表于 2021-5-25 19:05:45

79 是最大,79 + 1 = 80
80 是最小
80 < 88

你的数据里面没有 80,最小是 81
没有 79,最大是 78

另一个问题,边界错误
试试这个代码,最后一个数据是 80,最小
DATAS SEGMENT
    ;此处输入数据段代码
    org 0270H
    n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,80H
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    ;此处输入代码段代码
    mov si,0270H
    mov al,
    mov bl,al
    mov cl,0FH
    ;mov cl,10H
ks: inc si
    dec cl
    jz over
    cmp al,
    JLE next
    mov al,
next:cmp bl,
    JG ks
    mov bl,
    jmp ks
over:mov si,0280H
    mov ,bl
    add si,2
    mov ,al
    MOV AH,4CH
    INT 21H
CODES ENDS
END START

肖-肖 发表于 2021-5-25 19:31:30

人造人 发表于 2021-5-25 19:05
79 是最大,79 + 1 = 80
80 是最小
80 < 88


第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表0码?
还是说计算机中没有负数,看成是负数的话也是以补码的方式存放的?
比如81H-->源码--》1000 0001->反码--》1111 1110-》补码-》1111 1111-》FFH
比如89H-->源码->1000 1001->反码->1111 0110-> 补码-> 1111 0111-> F7H
那也应该是89H<81H啊?为什么81H小? 如果直接看成-1也是它大
比如80H-->源码-->1000 0000-->反码-->1111 1111-->补码-->1000 0000 溢出

第二个问题:边界错误是指的什么?
我以为 是比较次数写错了,可是没错啊,就是:0FH 15次啊

   

人造人 发表于 2021-5-25 20:13:13

肖-肖 发表于 2021-5-25 19:31
第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表 ...

负数用补码表示
补码是 原码取反再加 1
举例
求 -1 在内存中的值
原码
00000001
取反
11111110
加 1
11111111
各位全 1,就是 -1
-1 + 1 = 0
11111111 + 00000001 = 1 00000000
最高位丢弃,结果就是 0

-128
原码 128 是
10000000
取反
011111111
加 1
100000000
最高位是 1,其他全 0,是 -128

可以看成最高位是符号位
011111111最大,0x79
100000000最小,0x80,这是有符号数 -128
100000001是0x81,是有符号数 -127

1 < 2
2 < 3
3 < 4
...
0x78 < 0x79
79是最大,再加 1,就变成了最小
0x80(-128) < 0x81(-127)
0x81(-127) < 0x82(-126)

人造人 发表于 2021-5-25 20:14:32

肖-肖 发表于 2021-5-25 19:31
第一个问题:
为什么一个字节有符号数中:79为最大正数这个我理解,那为什么80是最小的负数呢?80不应该代表 ...

你运行这个代码,看 282h 的内容,最小应该是 0x80
DATAS SEGMENT
    ;此处输入数据段代码
    org 0270H
    n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,71H,85H,73H,75H,86H,76H,80H
DATAS ENDS

STACKS SEGMENT
    ;此处输入堆栈段代码
STACKS ENDS

CODES SEGMENT
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
    MOV AX,DATAS
    MOV DS,AX
    ;此处输入代码段代码
    mov si,0270H
    mov al,
    mov bl,al
    mov cl,0FH
    ;mov cl,10H
ks: inc si
    dec cl
    jz over
    cmp al,
    JLE next
    mov al,
next:cmp bl,
    JG ks
    mov bl,
    jmp ks
over:mov si,0280H
    mov ,bl
    add si,2
    mov ,al
    MOV AH,4CH
    INT 21H
CODES ENDS
END START

肖-肖 发表于 2021-5-25 20:50:59

人造人 发表于 2021-5-25 20:14
你运行这个代码,看 282h 的内容,最小应该是 0x80

我复制的代码 只粘贴个头好了
DATAS SEGMENT
    ;此处输入数据段代码
    org 0270H
    n db 81H,70H,82H,76H,84H,74H,83H,78H,88H,79H,85H,73H,75H,86H,76H,80H
DATAS ENDS
运行出来的是:

人造人 发表于 2021-5-25 20:52:10

肖-肖 发表于 2021-5-25 20:50
我复制的代码 只粘贴个头好了

运行出来的是:

应该是80才对呀,80最小

肖-肖 发表于 2021-5-25 20:54:46

人造人 发表于 2021-5-25 20:52
应该是80才对呀,80最小

那是为什么?为什么会输出这个?

肖-肖 发表于 2021-5-25 20:59:43

人造人 发表于 2021-5-25 20:52
应该是80才对呀,80最小

哦 我知道了 是你说的那个边界问题 原来如此 因为我是将第一个数给了寄存器所以需要比较16次
应该是10H
我改了之后就对了

肖-肖 发表于 2021-5-25 21:03:16

人造人 发表于 2021-5-25 20:14
你运行这个代码,看 282h 的内容,最小应该是 0x80

感谢大佬 感谢
页: [1]
查看完整版本: 还是一个有问题的程序,请指点一下