Как заменить специфический символ в процедуре Nasm - PullRequest
5 голосов
/ 22 июня 2019

Я хочу заменить пробелы в dbyte символом '#', и db должен быть передан в процедуру стеком.

Я написал следующий фрагмент, и замена работает, но я могу 'не понимаю, как правильно передать db в процедуру func.

org 0x100 
    push array
    call func
    mov bp, sp 
    mov bx, [bp]
    ret 

loop:
    mov al, byte[bx+si]
    cmp al, 0
     jz func
    cmp al , ' '
     jnz loop
    mov byte[bx+si], '#'
    inc si
    jmp loop
    ret

func:  
    push bp  
    mov bp, sp  
    mov bx, [bp + 4]    
    call loop
    mov [bp + 4], bx
    pop bp  
    ret 4 

array db "a b c", 0

1 Ответ

2 голосов
/ 22 июня 2019

Несколько проблем

push array
call func
;
ret 4

Это 16-битный код, поэтому массив передается как слово.Вместо этого ret 4 должно быть ret 2.Обратите внимание, что массив на самом деле является строкой .

*1014*

с нулевым символом. Это может не сработать, если вы не очистили SI заранее.

cmp al, 0
jz func

Вы в коде, который вы call отредактировали.Вы не должны прыгать назад к вызывающей стороне, как это!

cmp al , ' '
jnz loop

Этот прыжок к вершине пропускает приращение на SI.

mov [bp + 4], bx

Это избыточно, поскольку аргумент не был изменен.Более того, вы все равно откажетесь от него.

mov bp, sp 
mov bx, [bp]

Это полезно?Он просто загружает адрес возврата для последующего завершения программы.

ret

Этот способ завершения программы зависит от правильного стека.Это не всегда так!Программы DOS лучше завершать через:

mov ax, 4C00h
int 21h

Соединяя все вместе

 org  256

 push MyString
 call Func
 mov  bp, sp 
 mov  bx, [bp]
 mov  ax, 4C00h  ;Program termination
 int  21h

Loop:
 mov  al, byte[bx+si]
 cmp  al, 0
 je   EndOfLoop
 cmp  al, ' '
 jne  NotASpace
 mov  byte[bx+si], '#'
NotASpace:
 inc  si
 jmp  Loop
EndOfLoop:
 ret

;Clobbers AL, BX, SI
Func:  
 push bp  
 mov  bp, sp  
 mov  bx, [bp + 4]
 xor  si, si
 call Loop
 pop  bp  
 ret  2

MyString db "a b c", 0
...