assembly 汇编中的C的strstr()类似物

toe95027  于 7个月前  发布在  其他
关注(0)|答案(1)|浏览(68)

我试图使一个strstr模拟asm.但我挣扎.由于某种原因,代码不输出任何东西.我试图做的是:我把参数传递给堆栈上的 strstr proc,然后在 strstrinner_loop 中,我把指针指向我想搜索的第一个字符串的符号,之后我调用 search proc,在这里我对两个字符串进行了比较。
关于输入字符串-它的第一个字节是它的最大长度;输入后的第二个字节将包含实际长度(输入字符的数量)。这就是为什么我写[bp+6][bp+8]

assume cs:code, ds:data

data segment
    newline db 0Dh, 0Ah, '$'
    string1 db 100, 99 dup (0)
    string2 db 100, 99 dup (0)
    not_found_message db 'Not found', '$'
data ends

code segment
strstr proc
    push bp
    mov bp, sp

    mov di, [bp+4]
    add di, 2
    mov si, [bp+6]
    add si, 2

    inner_loop:
        mov al, [di]
        cmp al, '$'
        jne go_search
        je failed1

    go_search:
        push di
        push si
        call search

        pop ax

        cmp ax, 1
        je success1

        inc di
        jmp inner_loop

    success1:
        mov ax, di
        pop bp
        pop bx
        pop dx
        push ax
        push bx
        ret

    failed1:
        mov ax, -1
        pop bp
        pop bx
        pop dx
        push ax
        push bx
        ret
strstr endp

search proc
    push bp
    mov bp, sp

    mov di, [bp+10]
    mov si, [bp+12]

    custom_loop:
        mov al, [di]
        mov bl, [si]

        cmp bl, '$'
        je success2

        cmp al, '$'
        je failed2

        cmp al, bl
        je match

        jmp failed2

    match:
        inc di
        inc si
        jmp custom_loop

    success2:
        mov ax, 1
        pop bp
        pop bx
        pop dx
        push ax
        push bx
        ret

    failed2:
        pop bp
        pop bx
        pop dx
        push ax
        push bx
        ret
search endp

start:
    mov ax, data
    mov ds, ax

    mov dx, offset string1
    xor ax, ax
    mov ah, 0Ah
    int 21h
    push dx

    mov dx, offset newline
    mov ah, 09h
    int 21h

    mov dx, offset string2
    xor ax, ax
    mov ah, 0Ah
    int 21h
    push dx

    mov dx, offset newline
    mov ah, 09h
    int 21h

    call strstr

    pop ax

    cmp ax, -1
    je not_found

    print_result:
        mov cx, 10
        test ax, ax
        jz check_done

    check_done:
        xor dx, dx
        div cx
        push dx
        test ax, ax
        jnz check_done

    print_number:
        pop dx
        add dl, '0'
        mov ah, 02h
        int 21h

    mov ah, 4ch
    int 21h

not_found:
    mov ah, 09h
    mov dx, offset not_found_message
    int 21h

    mov ah, 4ch
    int 21h
code ends
end start

字符串
我认为错误在于使用堆栈。

biswetbf

biswetbf1#

我认为错误在于使用堆栈。
实际上,程序中的大多数错误都与如何处理堆栈有关。

  • strstrsearch 过程都是用堆栈上的两个参数调用的,但是这些过程错误地留下了它们的一个参数。这种情况发生在四个不同的场合。作为一个例子,考虑:
success1:
   mov ax, di    <- No need to transfer beforehand
   pop bp        <- Restore BP
   pop bx        <- Temporary removal of return address
   pop dx        <- Removal of one of the arguments
   push ax       <- Pushing the exit code
   push bx       <- Restoring the return address
   ret           <- The return address gets used

字符串
正确的顺序是:

success1:
    mov  [bp + 6], di  ; Overwrite one of the arguments with the exit code
    pop  bp            ; Restore BP
    ret  2             ; Return and let the CPU remove the other argument for you

  • search proc中,你甚至没有正确使用参数!
mov di, [bp+10]  <- Return address of 'strstr' ???
mov si, [bp+12]  <- One of the arguments of 'strstr' ???


正确的偏移量为:

mov  di, [bp + 4]    ; The second pushed argument
mov  si, [bp + 6]    ; The first pushed argument


为了更有意义,最好将两个过程的参数按相同的顺序排列:

push si              ; Where to search
push di              ; What to search
call search

  • 由于 search proc使用SI和DI寄存器用于其自身目的,因此在返回到 strstr proc时,您将不再能够正确地继续 inner_loop!保留这些寄存器是有序的:
search proc
  push bp             ; Preserve BP
  mov  bp, sp
  push si             ; Preserve SI
  push di             ; Preserve DI
  mov  si, [bp + 6]   ; Where to search
  mov  di, [bp + 4]   ; What to search
custom_loop:

    ...

success2:
  mov  ax, 1
failed2:
  mov  [bp + 6], ax  ; Overwrite with the exit code
  pop  di            ; Restore DI
  pop  si            ; Restore SI
  pop  bp            ; Restore BP
  ret  2
search endp


请注意,print_number 代码忘记在堆叠的地址上进行重复!您的结果是一个16位偏移地址,因此您可以期望一个数字最多有5个十进制数字。Displaying numbers with DOS详细解释了如何转换和显示数字。
使用DOS.BufferedInput函数0Ah也可以改进。在How buffered input works中阅读所有关于它的信息。

相关问题