如何以汇编语言

时间:2015-11-13 04:18:13

标签: string assembly reverse masm irvine32

所以我的任务是用汇编代码编写一个程序来编写一个语句,接收一个用户输入的字符串。打印该字符串然后使用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

但我没有得到任何输出。

它说"你好,(你的名字在这里)"

它说"这是你的名字倒退"

我已经尝试了几乎每一种不同的化身,我能想到并且无济于事。我在"字符串"的最后这里

2 个答案:

答案 0 :(得分:3)

这反对我更好的判断,因为反转的代码片段甚至没有被整合到原始海报创建的代码中。变量名称不同。快速而又脏的代码集成是创建一个变量 nameSize ,它保存从 ReadString 调用中读取的字符数。 ReadString(Irvine32库的一部分)返回在寄存器 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

我应该指出,如果你不介意摧毁原文,这是一种非常低效的反转字符串的方法。通过将字符串反转就可以在堆栈上没有辅助缓冲区的情况下完成。

答案 1 :(得分:0)

高层:

  • 分配'反向'和'文字'缓冲区
  • 将字符串读入'text'
  • 在文本末尾创建一个指针,将每个字符复制到开头,分别递减和递增。
  • 打印新的“反向”缓冲区。

也可以在不分配新缓冲区的情况下执行此操作,但通常应该避免,因为调用系统调用的成本(在每个字符之后需要执行此操作)

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