linux 为什么read宏使用rax而不是rdx来存储NASM代码中的字符串长度?

irlmq6kh  于 2023-06-05  发布在  Linux
关注(0)|答案(1)|浏览(134)
section .data
    msg db 10 "Enter string"
    msg_len equ $-msg
    
    
    smsg db 10 "Length is: "
    smsg_len equ $-smsg
    
    
    
    
    
section .bss
char_ans resb 2
string resb 50
string_len equ $-string
count resb 1
;----------------------------------

%macro print 2
mov rax, 1
mov rdi, 1
mov rsi, %1
mov rdx, %2
syscall
%endmacro

%macro read 2
mov rax, 0
mov rdi, 0
mov rsi, %1
mov rdx, %2
syscall
%endmacro

%macro exit 0
mov rax, 60
mov rsi, 0
syscall
%endmacro


;----------------------------------

section .text
    global _start

_start:

print msg, msg_len
read string, string_len


mov [count], rax

print smsg, smsg_len
mov rax, [count]
call display
exit


display:
    mov rbx, 16
    mov rcx, 2
    mov rsi, char_ans+1
    
cnt:
    mov rdx, 0
    div rbx
    cmp dl, 09h
    jbe add30
    add dl,37h
    
    add30:
        add dl, 30h
        mov [rsi], dl
        dec rsi
        dec rcx
        jnz cnt
print char_ans, 2
ret

我觉得应该是

section .text
    global _start

_start:

print msg, msg_len
read string, string_len

mov rax, rdx               ;VALUE OF RDX MOVED TO RAX SINCE string_leN STORED IN rdx
mov [count], rax

print smsg, smsg_len
mov rax, [count]
call display
exit
s3fp2yjn

s3fp2yjn1#

为什么使用RAX

如果一个程序显示“输入字符串”,后面跟着“长度是:”,那么提到的长度应该与实际输入的字符串的字符数有关。所以,输入所进入的缓冲区的长度不是很重要,因为这是一个微不足道的信息,即使在程序启动之前,你也知道。
当使用SYSREAD函数时(通过宏或不通过宏),是您提供RDX寄存器中的缓冲区长度,并在返回时,是系统函数为您提供RAX寄存器中输入字符串的(正)长度(如果一切顺利,否则您将在RAX中收到一些负值)。

进一步审核

mov rax, 60
mov rsi, 0
syscall

SYSEXIT的返回码属于RDI寄存器。打字错误?

count resb 1
...
mov [count], rax

如果您只为 count 变量保留一个字节,那么您不应该在该变量中存储完整的qword。这是一个程序中灾难的配方。

cmp dl, 09h
  jbe add30
  add dl,37h
add30:
  add dl, 30h

您的 display 代码在显示长度10及以上时会出现问题。十六进制数A到F所需的额外增量为7。您错误地添加了37h,当且仅当您跳过add dl, 30h指令时才是正确的,这是任何人都不应该做的事情。
这是您可以编写此转换的多种方法之一。重要的是要注意,对于十六进制转换,您可以通过向右移动4次来替换除以16。除法运算是一种代价很高的操作,尤其是您正在使用的128位除法运算。

; IN (al)
display:
  mov  ecx, 1
cnt:
  mov  edx, eax             ; (1)
  and  al, 15
  cmp  al, 10
  jb   .digit
  add  al, 7
.digit:
  add  al, '0'
  mov  [char_ans + rcx], al
  mov  eax, edx             ; (1)
  shr  eax, 4               ; Replaces division by 16
  dec  ecx
  jns  cnt
  print char_ans, 2
  ret

相关问题