如何用汇编语言反转和打印字符串
How to reverse and print a string in assembly language
所以我的任务是用汇编代码编写一个程序,该程序可以进行声明,接收用户输入的字符串。打印该字符串,然后使用 cpu 堆栈将其反转并再次打印。这就是我目前所拥有的。
INCLUDE Irvine32.inc
.data
buffer byte 20 DUP(0)
byteCount DWORD ?
Question byte "Please enter your name." ,0
Greeting byte "Hello " ,0
Statement byte " Here is your name backwards"
.code
main proc
mov edx , OFFSET Question
call WriteString
call CRLF
Call CRLF
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
push edx
mov EDX ,OFFSET greeting
Call WriteString
pop edx
call WriteString
Call CRLF
Call CRLF
如您所见,它成功地接受了用户输入并显示了它,但我真的很努力地试图扭转它。
我在这里尝试了这些,我从书中关于反转字符串的一章中复制了这些内容。
; Push the name on the stack.
mov ecx,nameSize
mov esi,0
L1: movzx eax,aName[esi] ; get character
push eax ; push on stack
inc esi
loop L1
; Pop the name from the stack in reverse
; and store it in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov aName[esi],al ; store in string
inc esi
loop L2
Invoke ExitProcess,0
main endp
end main
但我没有得到任何输出。
它说 "hello, (yourname here)"
它说 "this is your name backwards "
我尝试了几乎所有我能想到的不同版本,但都无济于事。我在 "string" 的结尾
这违背了我更好的判断,因为用于反转的代码片段甚至没有集成到原始发布者创建的代码中。变量名称不同。代码的快速集成是创建一个变量 nameSize,它保存从调用 ReadString 中读取的字符数。 ReadString(Irvine32 库的一部分)returns 寄存器中读取的字符数 EAX.
在 .data
部分添加变量:
nameSize DWORD ?
在 ReadString 之后将 EAX 寄存器的内容移动到 nameSize。此代码:
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
应该是:
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
mov nameSize, eax ; EAX contains number of characters read into buffer
在用于反转代码的代码片段中,删除底部的用于过程结束的行等。不需要这些,因为我们将在我们的原始代码中执行此操作。
Invoke ExitProcess,0
main endp
end main
在我们看到变量 aName 的字符串反转代码中的任何地方都将其更改为 buffer 因为这是我们放置用户名的地方.将该代码放入我们的程序中,并使用 WriteString 在最后打印反向缓冲区。代码可能类似于:
INCLUDE Irvine32.inc
.data
buffer byte 20 DUP(0)
byteCount DWORD ?
nameSize DWORD ?
Question byte "Please enter your name." ,0
Greeting byte "Hello " ,0
Statement byte " Here is your name backwards"
.code
main proc
mov edx , OFFSET Question
call WriteString
call CRLF
Call CRLF
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
mov nameSize, eax
push edx
mov EDX ,OFFSET greeting
Call WriteString
pop edx
call WriteString
Call CRLF
Call CRLF
mov ecx,nameSize
mov esi,0
L1: movzx eax,buffer[esi] ; get character
push eax ; push on stack
inc esi
loop L1
; Pop the name from the stack in reverse
; and store it in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov buffer[esi],al ; store in string
inc esi
loop L2
mov EDX ,OFFSET buffer
call WriteString ; Write the reversed string that is now in buffer
exit
main ENDP
END
如果您遇到链接错误,您可能没有链接所有必备库。尝试将这些行添加到程序的顶部:
INCLUDE Irvine32.inc
INCLUDELIB Irvine32.lib
INCLUDELIB user32.lib
INCLUDELIB kernel32.lib
我应该指出,如果您不介意破坏原始字符串,这是一种非常低效的反转字符串的方法。可以通过在适当的位置反转字符串来在堆栈上没有辅助缓冲区的情况下完成。
高级别:
- 分配 'reverse' 和 'text' 缓冲区
- 将字符串读入'text'
- 在文本末尾创建一个指针,将每个字符复制到开头,分别递减和递增。
- 打印新的 'reverse' 缓冲区。
在不分配新缓冲区的情况下执行此操作也是可能的,但通常应该避免,因为调用系统调用的成本(您需要在每个字符之后执行)
section .data
prompt db "Please enter your name: ", 10
length equ $ - prompt
text times 255 db 0
buffer times 255 db 0
Enter your text
section .text
global main
main:
mov rax, 1
mov rdi, 1
mov rsi, prompt
mov rdx, length
syscall
mov rax, 0
mov rdi, 0
mov rsi, text
syscall
mov rcx, rax ; rcx will be the character counter.
mov rsi, text ; a pointer to the current character. Start from the beginning.
add rsi, rcx
dec rsi ; Remember the 0-index
mov rdi, buffer
;; This subroutine is also SUB-optimal if your teacher demands
;; performance, look into the advantages of `lea` and a simple
;; rep;scas loop as well.
process_loop:
mov bl, [rsi] ; Now copy from back to front
mov [rdi], bl
inc rdi
dec rsi
dec rax
jnz process_loop
mov rax, 1 ; And print the string
mov rdi, 1
mov rsi, buffer
mov rdx, rcx
syscall
exit:
mov rax, 60
mov rdi, 0
syscall
所以我的任务是用汇编代码编写一个程序,该程序可以进行声明,接收用户输入的字符串。打印该字符串,然后使用 cpu 堆栈将其反转并再次打印。这就是我目前所拥有的。
INCLUDE Irvine32.inc
.data
buffer byte 20 DUP(0)
byteCount DWORD ?
Question byte "Please enter your name." ,0
Greeting byte "Hello " ,0
Statement byte " Here is your name backwards"
.code
main proc
mov edx , OFFSET Question
call WriteString
call CRLF
Call CRLF
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
push edx
mov EDX ,OFFSET greeting
Call WriteString
pop edx
call WriteString
Call CRLF
Call CRLF
如您所见,它成功地接受了用户输入并显示了它,但我真的很努力地试图扭转它。
我在这里尝试了这些,我从书中关于反转字符串的一章中复制了这些内容。
; Push the name on the stack.
mov ecx,nameSize
mov esi,0
L1: movzx eax,aName[esi] ; get character
push eax ; push on stack
inc esi
loop L1
; Pop the name from the stack in reverse
; and store it in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov aName[esi],al ; store in string
inc esi
loop L2
Invoke ExitProcess,0
main endp
end main
但我没有得到任何输出。
它说 "hello, (yourname here)"
它说 "this is your name backwards "
我尝试了几乎所有我能想到的不同版本,但都无济于事。我在 "string" 的结尾
这违背了我更好的判断,因为用于反转的代码片段甚至没有集成到原始发布者创建的代码中。变量名称不同。代码的快速集成是创建一个变量 nameSize,它保存从调用 ReadString 中读取的字符数。 ReadString(Irvine32 库的一部分)returns 寄存器中读取的字符数 EAX.
在 .data
部分添加变量:
nameSize DWORD ?
在 ReadString 之后将 EAX 寄存器的内容移动到 nameSize。此代码:
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
应该是:
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
mov nameSize, eax ; EAX contains number of characters read into buffer
在用于反转代码的代码片段中,删除底部的用于过程结束的行等。不需要这些,因为我们将在我们的原始代码中执行此操作。
Invoke ExitProcess,0
main endp
end main
在我们看到变量 aName 的字符串反转代码中的任何地方都将其更改为 buffer 因为这是我们放置用户名的地方.将该代码放入我们的程序中,并使用 WriteString 在最后打印反向缓冲区。代码可能类似于:
INCLUDE Irvine32.inc
.data
buffer byte 20 DUP(0)
byteCount DWORD ?
nameSize DWORD ?
Question byte "Please enter your name." ,0
Greeting byte "Hello " ,0
Statement byte " Here is your name backwards"
.code
main proc
mov edx , OFFSET Question
call WriteString
call CRLF
Call CRLF
mov edx, OFFSET buffer
mov Ecx, SIZEOF buffer
call ReadString
mov nameSize, eax
push edx
mov EDX ,OFFSET greeting
Call WriteString
pop edx
call WriteString
Call CRLF
Call CRLF
mov ecx,nameSize
mov esi,0
L1: movzx eax,buffer[esi] ; get character
push eax ; push on stack
inc esi
loop L1
; Pop the name from the stack in reverse
; and store it in the aName array.
mov ecx,nameSize
mov esi,0
L2: pop eax ; get character
mov buffer[esi],al ; store in string
inc esi
loop L2
mov EDX ,OFFSET buffer
call WriteString ; Write the reversed string that is now in buffer
exit
main ENDP
END
如果您遇到链接错误,您可能没有链接所有必备库。尝试将这些行添加到程序的顶部:
INCLUDE Irvine32.inc
INCLUDELIB Irvine32.lib
INCLUDELIB user32.lib
INCLUDELIB kernel32.lib
我应该指出,如果您不介意破坏原始字符串,这是一种非常低效的反转字符串的方法。可以通过在适当的位置反转字符串来在堆栈上没有辅助缓冲区的情况下完成。
高级别:
- 分配 'reverse' 和 'text' 缓冲区
- 将字符串读入'text'
- 在文本末尾创建一个指针,将每个字符复制到开头,分别递减和递增。
- 打印新的 'reverse' 缓冲区。
在不分配新缓冲区的情况下执行此操作也是可能的,但通常应该避免,因为调用系统调用的成本(您需要在每个字符之后执行)
section .data
prompt db "Please enter your name: ", 10
length equ $ - prompt
text times 255 db 0
buffer times 255 db 0
Enter your text
section .text
global main
main:
mov rax, 1
mov rdi, 1
mov rsi, prompt
mov rdx, length
syscall
mov rax, 0
mov rdi, 0
mov rsi, text
syscall
mov rcx, rax ; rcx will be the character counter.
mov rsi, text ; a pointer to the current character. Start from the beginning.
add rsi, rcx
dec rsi ; Remember the 0-index
mov rdi, buffer
;; This subroutine is also SUB-optimal if your teacher demands
;; performance, look into the advantages of `lea` and a simple
;; rep;scas loop as well.
process_loop:
mov bl, [rsi] ; Now copy from back to front
mov [rdi], bl
inc rdi
dec rsi
dec rax
jnz process_loop
mov rax, 1 ; And print the string
mov rdi, 1
mov rsi, buffer
mov rdx, rcx
syscall
exit:
mov rax, 60
mov rdi, 0
syscall