复制字符串时出错 - ASM

时间:2014-02-06 14:55:50

标签: string assembly masm ia-32

我正在研究一本装配书,而且,该程序将origen中包含的字符串复制到destino。程序编译没有错误,但当我执行它时,Windows说:“程序需要关闭”。

我正在编写IA-32程序集,并使用Qeditor进行编译。

这是代码:

.386
.model flat,stdcall
option casemap:none

.data
origen BYTE  "Esta es la cadena de origen",0 ; "This is the source string",0
destino BYTE  SIZEOF origen DUP(0)

.code

start:
mov  esi,0 ; index register
mov  ecx,SIZEOF origen ; loop counter

L1:
    mov al,origen[esi] ; obtain a character from origen
    mov destino[esi],al ; store character in destino
    inc esi ; move to next character
    loop L1 ; repeat the process for all characters contained in the string

END start

我试过调试它,但是当完成循环时,程序有访问错误。我不明白为什么。 请帮忙。 调试:http://www.subirimagenes.com/otros-captura1-8802120.html

谢谢。

==========

解决方案

我编写了一些代码,但是相同。

.386
.model flat,stdcall
option casemap:none

include     \masm32\include\kernel32.inc
include     \masm32\include\masm32.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\masm32.lib ; StdIn, StdOut

.data
origen BYTE  "Hello world.",0
destino BYTE  SIZEOF origen DUP(0)

.code
main PROC
    mov  esi,0 ; registro í­ndice
    mov  ecx,LENGTHOF origen ; ECX = 12 veces


bucle:
    mov al,[origen + esi]
    mov [destino + esi],al
    add esi,TYPE origen
    loop bucle

    ; Wheen loop finish, execute this:
    invoke StdOut, OFFSET destino ; print
    invoke ExitProcess, 0 ; exit
main ENDP
END main

6 个答案:

答案 0 :(得分:3)

循环退出后没有任何东西可以终止程序。它必须显式调用“退出程序”系统调用,或者返回调用者,或者它结束时应该做的任何事情。

正如所写的那样,它只是继续执行超出loop指令的内存,无论发生在那里的字节是什么。那肯定不是你想要的。

答案 1 :(得分:0)

循环永远不会结束。 编辑:实际上它结束了。

您可以这样做:

mov  esi,0 ; index register
mov  ecx,SIZEOF origen ; loop counter

L1:
    mov al,origen[esi] ; obtain a character from origen
    mov destino[esi],al ; store character in destino
    inc esi ; move to next character
    cmp esi, ecx ; set flags
    jne L1 ; repeat the process for all characters contained in the string if index != size

END start

答案 2 :(得分:0)

是的,我没有打电话给退出。 好吧,我编写了一个退出程序,但是我想在完成循环时执行打印(StdOut)。 我是怎么做到的?实际上程序不会打印字符串,因为没有执行StdOut。

Cyril Fougeray :有了这个我有同样的问题,而且LOOP有一个条件(ECX)。

.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\masm32.inc
includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\masm32.lib ; StdIn, StdOut

.data
origen BYTE  "Esta es la cadena de origen",0
destino BYTE  SIZEOF origen DUP(0)

.code
start:
    mov  esi,0
    mov  ecx,SIZEOF origen
    jmp L1
    invoke StdOut, OFFSET destino
    invoke ExitProcess, 0

L1:
    mov al,origen[esi]
    mov destino[esi],al
    inc esi
    loop L1


END start

答案 3 :(得分:0)

移动字符串是经常使用的操作,因此它在x86汇编中有自己的机器指令:

start:
    mov esi,OFFSET origen
    mov edi,OFFSET destino
    mov ecx,SIZEOF destino
    cld 
    rep movsb
    ret

答案 4 :(得分:0)

你应该摆脱 spaghetti jmp L1 ,否则你的过程永远不会在循环结束后调用StdOut

.data
    origen BYTE  "Esta es la cadena de origen",0
    destino BYTE  SIZEOF origen DUP(0)
    BytesWritten DWORD 0
.code
start:
    mov  esi,0
    mov  ecx,SIZEOF origen
L1:
    mov al,origen[esi]
    mov destino[esi],al
    inc esi
    loop L1
    invoke StdOut, OFFSET destino
    invoke ExitProcess, 0

如果调用MASM的宏 StdOut 仍然没有输出,请参阅 masm32 invoking stdout gives no output 在Windows中,我更喜欢本地写入标准输出的方法:

  invoke GetStdHandle,STD_OUTPUT_HANDLE ; get standard output handle to EAX
  invoke WriteFile,EAX,OFFSET destino, SIZEOF origen,OFFSET BytesWritten,0 ; write destino to StdOut

有关theese Windows功能的更多信息,请参阅 http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx http://msdn.microsoft.com/en-us/library/aa910675.aspx

答案 5 :(得分:0)

我在8天前看到了这个问题并假设你已经解决了。基本上Wally在开​​始时是正确的。

你的应用程序在代码执行后继续处理垃圾代码,因为它没有被告知何时停止=给自己一个好的反汇编程序。由于您没有使用堆栈并且它保持平衡,您只需在代码后提供“retn”。

使用Windows库(您在MASM下发布)通常会发出kernel32中包含的“调用ExitProcess”。

以下内容将按预期工作(但不会输出任何内容,因为您未指定需要):

.386
.MODEL flat, stdcall
OPTION CASEMAP:NONE 

.data
origen db "Esta es la cadena de origen",0 ; Source string zero terminated
destino db SIZEOF origen dup(0) ;Buffer zero initialised

.code

Start:

xor esi,esi ;esi = 00000000
xor eax,eax ;eax = 00000000
mov ecx,sizeof origen ;loop counter

L1:
mov al,origen[esi] ;get a byte from esi (character from 'origen')
mov destino[esi],al ;store byte (character) in 'destino'
inc esi ;move to next byte (character)
loop L1

retn ;magic instruction!

End Start