我提供了两种不同的计算字符串长度时切换段的实现。我不明白为什么我们要切换额外段和数据段,或者更准确地说,将数据段(寄存器 DS)的内容复制到额外段(寄存器 ES)。如果我删除这些行push ds
,pop es
结果不会改变,但是当我les di, [bp+4]
用替换时mov di, [bp+4]
,屏幕上会显示消息,但带有一堆其他不同的字符。
为什么会发生这种情况?我是装配方面的新手。
org 0x0100
jmp start
message: db 'Hello world!', 0 ; First string to be concatenated
; Subroutine to calculate the length of a string
; Takes the segment and offset of a string as parameters
strlen:
push bp
mov bp, sp
push es
push cx
push di
les di, [bp+4] ; Point es:di to string
mov cx, 0xffff ; Load maximum number in cx
xor al, al ; Load a zero in al
repne scasb ; Find zero in the string
mov ax, 0xffff ; Load maximum number in ax
sub ax, cx ; Find change in cx
dec ax ; Exclude null from length
pop di
pop cx
pop es
pop bp
ret 4
; Subroutine to print a string
; Takes the x position, y position, attribute, and address of a null-terminated string as parameters
printstr:
push bp
mov bp, sp
pusha
push di
push ds ; Push segment of string
mov ax, [bp+4]
push ax ; Push offset of string
call strlen ; Calculate string length
cmp ax, 0 ; Is the string empty?
jz exit ; No printing if string is empty
mov cx, ax ; Save length in cx
mov ax, 0xb800 ; Video memory base address
mov es, ax ; Point es to video base
mov al, 80 ; Load al with columns per row
mul byte [bp+8] ; Multiply with y position
add ax, [bp+10] ; Add x position
shl ax, 1 ; Turn into byte offset
mov di, ax ; Point di to required location
mov si, [bp+4] ; Point si to string
mov ah, [bp+6] ; Load attribute in ah
cld ; Clear direction flag for auto-increment mode
nextchar:
lodsb ; Load next char in al
stosw ; Print char/attribute pair
loop nextchar ; Repeat for the whole string
exit:
pop ds
pop di
popa
pop bp
ret 8
start:
mov ax, 30
push ax ; Push x position
mov ax, 20
push ax ; Push y position
mov ax, 0x7 ; Blue on white attribute
push ax ; Push attribute
mov ax, message
push ax ; Push address of message
call printstr ; Call the printstr subroutine
mov ax, 0x4c00 ; Terminate program
int 0x21
替代版本:
push bp
mov bp, sp
pusha
push ds
pop es ; load ds in es
mov di, [bp+4] ; point di to string
mov cx, 0xffff ; load maximum number in cx
xor al, al
repne scasb
mov ax, 0xffff
sub ax, cx
dec ax
jz done
mov cx, ax
...