Windows(x86)程序集向输入的字符串追加空终止符

Windows(x86)程序集向输入的字符串追加空终止符,windows,string,assembly,x86,append,Windows,String,Assembly,X86,Append,我当前正在尝试向(a?)用户输入的字符串追加空终止符: .386 .model flat, stdcall WriteFile PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED ReadFile PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED GetStdHandle PROTO STDCALL:DWORD .data buff

我当前正在尝试向(a?)用户输入的字符串追加空终止符:

.386
.model flat, stdcall

WriteFile PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED
ReadFile  PROTO STDCALL:DWORD, :PTR, :DWORD, :PTR DWORD, :PTR OVERLAPPED
GetStdHandle PROTO STDCALL:DWORD

.data
    buff            DB 100h DUP(?)
    stdInHandle     DWORD 0
    bytesRead       DWORD ?

.code
    start:
            ;read string from stdin
            INVOKE GetStdHandle, -10
            MOV stdInHandle, eax
            INVOKE ReadFile, stdInHandle, BYTE PTR[buff], 100, ADDR bytesRead, 0

            ;append null terminator on CR,LF
            MOV eax, bytesRead
            MOV edx, BYTE PTR[buff]
            SUB eax, 2
            AND BYTE PTR [eax+edx], 0
            RET
    END start
它拒绝在
MOV-edx,BYTE PTR[buff]
处组装,并给我一个错误:
错误:操作码和操作数的组合无效(或CPU设置错误)。

所以我假设我不能将
MOV
字节PTR[buff]的值写入寄存器edx。因此,我甚至无法开始测试这种尝试将
NULL
终止符应用于字符串的方法是否有效

我的问题是,上面的代码有什么问题(我应该使用不同的寄存器而不是edx吗?)


对字符串应用
NULL
终止符的最佳方法是什么

不能将字节值移动到dword大小的寄存器中。您需要使用字节大小的寄存器,如
dl
,或者使用
movzx
对其进行零扩展。在处理字节时,我建议使用第一个选项。

不能将字节值移动到dword大小的寄存器中。您需要使用字节大小的寄存器,如
dl
,或者使用
movzx
对其进行零扩展。当您使用字节时,我建议您使用第一个选项。

这非常常见,因此MASM32运行时将此功能作为其运行时的一部分提供。您只需包含相关代码:

include \masm32\include\masm32rt.inc
然后使用
StripLF
功能,如下所示:

invoke StripLF, addr buff
要解决当前问题(如果您想手动执行),您需要将
buff
的地址改为
edx

mov edx, offset buff

这是如此常见,以至于MASM32运行时将此功能作为其运行时的一部分提供。您只需包含相关代码:

include \masm32\include\masm32rt.inc
然后使用
StripLF
功能,如下所示:

invoke StripLF, addr buff
要解决当前问题(如果您想手动执行),您需要将
buff
的地址改为
edx

mov edx, offset buff

当我必须为字符串创建方法而不使用good ole Irvine中的任何内容时,我得到了字符串的长度,将返回的长度(需要为空终止符添加一个额外的+1)增加1,然后在指针位于计数器所在的字符串末尾添加0h

MOV     EAX, SIZEOF lpSourceString + 1      ; Get the string length of string, add 1 to include null-terminator
INVOKE allocMem, EAX                    ; Allocate memory for a target to copy to
LEA     ESI, [lpSourceString]           ; put source address in ESI
MOV     EDI, EAX                        ; copy the dest address to another register we can increment
MOV     ECX, SIZEOF lpSourceString      ; Set up loop counter 
我们有绳子的大小。现在我们可以将null终止添加到它。为此,我们需要确保有一个指针指向字符串的末尾。因此,如果我们有一个在EAX中返回字符串的方法,EAX需要指向字符串的开头(因此我们不修改
allocMem
,而是增加EDI中的副本)。假设我们将字符放入字符串中:

nextByte:                   ; Jump label, get the next byte in the string until ECX is 0
MOV     DL, [ESI]           ; Get the next character in the string
MOV     [EDI], DL           ; Store the byte at the position of ESI
INC     ESI                 ; Move to next char in source
INC     EDI                 ; INCrement EDI by 1
loop nextByte               ; Re-loop to get next byte

MOV     byte ptr[EDI], 0h   ; Add null-terminator to end of string

; EAX holds a pointer to the start of the dynamically-allocated
; 0-terminated copy of lpSourceString
MOV需要
字节ptr
大小说明符,因为
[EDI]
内存操作数和
0
立即操作数都不会暗示操作的大小。汇编程序不知道您指的是字节、字还是dword存储


我在我的MASM中有这个,但是我使用了一个由于类要求而编写的
String\u length
stdcall方法。

当我必须为字符串创建方法而不使用good ole Irvine中的任何内容时,我得到了字符串的长度,将返回的长度(需要为空终止符添加一个额外的+1)增加1,然后在字符串末尾添加0h,指针所在的位置是计数器所在的位置

MOV     EAX, SIZEOF lpSourceString + 1      ; Get the string length of string, add 1 to include null-terminator
INVOKE allocMem, EAX                    ; Allocate memory for a target to copy to
LEA     ESI, [lpSourceString]           ; put source address in ESI
MOV     EDI, EAX                        ; copy the dest address to another register we can increment
MOV     ECX, SIZEOF lpSourceString      ; Set up loop counter 
我们有绳子的大小。现在我们可以将null终止添加到它。为此,我们需要确保有一个指针指向字符串的末尾。因此,如果我们有一个在EAX中返回字符串的方法,EAX需要指向字符串的开头(因此我们不修改
allocMem
,而是增加EDI中的副本)。假设我们将字符放入字符串中:

nextByte:                   ; Jump label, get the next byte in the string until ECX is 0
MOV     DL, [ESI]           ; Get the next character in the string
MOV     [EDI], DL           ; Store the byte at the position of ESI
INC     ESI                 ; Move to next char in source
INC     EDI                 ; INCrement EDI by 1
loop nextByte               ; Re-loop to get next byte

MOV     byte ptr[EDI], 0h   ; Add null-terminator to end of string

; EAX holds a pointer to the start of the dynamically-allocated
; 0-terminated copy of lpSourceString
MOV需要
字节ptr
大小说明符,因为
[EDI]
内存操作数和
0
立即操作数都不会暗示操作的大小。汇编程序不知道您指的是字节、字还是dword存储


我的MASM中有这个,但是我使用了一个
String\u length
stdcall方法,这是我根据类的要求编写的;现在t是说
和BYTE PTR[eax+dl],0
指定了一个无效的地址,我感觉我真的走错了方向。在寻址时,不能混合不同大小的寄存器,在这种情况下,需要将偏移量零扩展到整个
edx
.Hmm,这样做似乎给了我一个访问违规和程序只是崩溃。。。根据我的调试器,在输入值后立即引发访问冲突,并跳到:
和字节PTR[eax+edx],0
,然后在该步骤后崩溃。根据我的调试器,
EDX
的值也始终保持
0
。对不起,如果我很烦人的话。我真的很困惑。你已经解决了他眼前的问题,但却忽略了他代码不起作用的大局。你正在取消对
buff
edx
应该包含地址。这解决了一个问题;现在t是说
和BYTE PTR[eax+dl],0
指定了一个无效的地址,我感觉我真的走错了方向。在寻址时,不能混合不同大小的寄存器,在这种情况下,需要将偏移量零扩展到整个
edx
.Hmm,这样做似乎给了我一个访问违规和程序只是崩溃。。。根据我的调试器,在输入值后立即引发访问冲突,并跳到:
和字节PTR[eax+edx],0
,然后在该步骤后崩溃。根据我的调试器,
EDX
的值也始终保持
0
。对不起,如果我很烦人的话。我真的很困惑。你已经解决了他眼前的问题,但却忽略了他的代码为什么不起作用的大局。你正在取消对
buf的引用