1

我目前正在尝试将空终止符附加到(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]并给我一个错误:
error: Invalid combination of opcode and operands (or wrong CPU setting).

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

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

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

4

3 回答 3

2

您不能将字节值移动到双字大小的寄存器中。您要么需要使用字节大小的寄存器,例如dl,要么使用movzx. 当您使用字节时,我建议您使用第一个选项。

于 2012-10-05T14:37:20.550 回答
2

当我不得不为字符串创建方法而不使用来自好 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 

我们有字符串的大小。现在我们可以向它添加空终止符。为此,我们需要确保有一个指向字符串末尾的指针。因此,如果我们有一个在 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 需要byte ptr大小说明符,因为[EDI]内存操作数和0直接操作数都不会暗示操作的大小。汇编器不会知道您的意思是字节、字还是双字存储。

我在我的 MASM 中有这个,但是String_length由于类要求,我使用了我编写的 stdcall 方法。

于 2019-04-20T21:21:32.013 回答
1

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

include \masm32\include\masm32rt.inc

然后StripLF像这样使用函数:

invoke StripLF, addr buff

要解决您当前的问题(如果您想手动解决),您需要将地址移动buffedx

mov edx, offset buff
于 2012-10-05T15:05:29.587 回答