查找数组中的最小值(Intel8086)

时间:2016-03-26 12:32:26

标签: assembly x86-16 tasm

我想编写一个简单的程序来查找数组中最小值。我使用的是英特尔8086架构(如果我对吗?)。问题是我对汇编语言完全不熟悉,我只是无法弄清楚我的代码中出了什么问题,我被卡住了。

最后(退出前)我的ax注册不包含我的结果 我担心它甚至不会放在那里(我用Turbo Debugger工具检查寄存器和值)。

.MODEL TINY

Data SEGMENT
                        arr_len     EQU 5
                        arr         DB 07h, 02h, 03h, 10h, 12h
                        minimum     DB 255
Data ENDS

Code SEGMENT
                        ORG 100h
                        ASSUME CS:Code, DS:Data, SS:Code
Start:
                        mov ax, SEG Data
                        mov ds, ax  ;load data to ds reg    
                        mov cx, arr_len ;arr_length to counter
                        mov bx, OFFSET arr ;load first elem.
Search: 
                        inc bx
                        cmp bl, [minimum] ;compare loaded elem with min
                        jb Swap ;if bl<minimum
Swap:
                        mov minimum, bl
                        loop Search         

                        mov al, minimum ;result here?
                        mov ax, 4C00h
                        int 21h

Code ENDS
END Start

有人能告诉我这里有什么问题吗?提前谢谢。

2 个答案:

答案 0 :(得分:4)

  • 微型模型不需要明确设置DS。 (CS = DS = ES = SS)
  • 由于BX第一次指向你的阵列,你不应该立即增加它!在循环之前执行inc
  • 你没有真正比较一个数组元素,而是比较迭代数组的地址的低字节。
  • 将4C00h放入AX后直接退出后,将任何结果放入AL是没有意义的。使用调试器查看AL可能会有效。

这是一个可行的版本:

Search: 
    mov al, [bx]
    cmp al, [minimum] ;compare loaded elem with min
    jnb NoSwap        ;if al>=minimum
    mov [minimum], al ;New minimum
NoSwap:
    inc bx
    loop Search

答案 1 :(得分:2)

就像Fifoernik的答案所解释的那样,你的条件分支是否会跳到同一个地方,因为分支目标是下一个insn。

如果你积累了minimum而没有将minimum留在记忆中,那么该如何做到这一点,因为那太可怕了。

此版本在al中累积mov,从不将其存储到内存中。我也使用字符串操作来获得乐趣。您将获得更小的代码大小,但可能比使用si加载代码更慢。使用loop作为源指针是一种很好的约定,可以帮助人类跟踪事物,即使不使用字符串操作也是如此。当然,不要让代码变得更糟,但是当你有选择时我会推荐它。

我也避免loop,因为it's slow and wasn't gaining us much of anything。除非您在代码大小超速的情况下进行硬核优化,否则请不要使用.MODEL TINY Data SEGMENT arr DB 07h, 02h, 03h, 10h, 12h arr_len EQU $-arr ; let the assembler calculate the size to avoid mistakes Data ENDS Code SEGMENT ORG 100h ASSUME CS:Code, DS:Data, SS:Code unsigned_min: ;; segment setup not needed with tiny model, according to Fifoernik ; assume arr_len >= 2 mov si, OFFSET arr ; src pointer = &first element lea di, [si + arr_len] ; end pointer. ;; mov di, arr_len + OFFSET arr ; also works, since input pointer is static ;; or use arr_len + OFFSET arr as an immediate operand for the loop condition, if you don't care about keeping the hard-coded input address out of the loop itself. cld ; clear the direction flag so string insns count upwards. Omit if the ABI guarantees this state already lodsb ; al = min so far = first element, and advance si to point to the second element ;; on entry: AL = 1st element (min). SI = pointer to 2nd element. DI = end-pointer Search: cmpsb ; compare [si] with current min (al), and ++si jae .no_new_min mov al, [si-1] ; conditionally skipped. You could use `cmov` instead of the branch on a CPU supporting 686 insns .no_new_min cmp si, di ; loop while si < end jb Search ; min is in AL mov ah, 4Ch ; exit with AL as exit status int 21h

arr_len >= 2

如果你不能假设cmp si,di,那么将min初始化为255或第一个元素,然后输入指向第一个元素而不是第二个元素的循环。或者在循环外使用额外的jb / readme.md