gpt4 book ai didi

windows - 将字符串参数传递给 PROC

转载 作者:可可西里 更新时间:2023-11-01 11:41:52 25 4
gpt4 key购买 nike

我想调用一个函数,该函数将对用户键入的字符串执行大写到小写的转换,同时保留特殊字符。这部分有效,但仅适用于前 4 个字符,之后的所有字符都会被截断。我相信这是因为我将参数定义为 DWORD:

我试过使用PAGEPARABYTE。前两个不起作用,字节表示类型不匹配。

upperToLower proc, source:dword, auxtarget:dword
mov eax, source ;Point to string
mov ebx, auxtarget ; point to destination
L1:
mov dl, [eax] ; Get a character from buffer
cmp byte ptr [eax], 0 ; End of string? (not counters)
je printString ; if true, jump to printString
cmp dl, 65 ; 65 == 'A'
jl notUpper ; if less, it's not uppercase
cmp dl, 90 ; 90 == 'Z'
jg notUpper ; if greater, it's not uppercase
xor dl, 100000b ; XOR to change upper to lower
mov [ebx], dl ; add char to target
inc eax ; Move counter up
inc ebx ; move counter up
jmp L1 ; loop

notUpper: ; not uppercase
mov [ebx], dl ; copy the letter
inc eax ;next letter
inc ebx
jmp L1

printString:
invoke WriteConsoleA, consoleOutHandle, auxtarget, sizeof auxtarget, bytesWritten, 0
ret
upperToLower endp

原型(prototype):

  upperToLower PROTO,
source: dword,
auxtarget: dword

调用:

    invoke upperToLower, offset buffer, offset target

缓冲区参数为:buffer db 128 DUP(?)

如何打印整个字符串,而不仅仅是前 4 个字符?

最佳答案

为什么只打印了 4 个字符?您将字符串写入控制台:

invoke WriteConsoleA,   consoleOutHandle, auxtarget, sizeof auxtarget, bytesWritten,    0

sizeof auxtarget 参数是 auxtarget 的大小,它是一个 DWORD(4 个字节),因此您只要求打印 4 个字节.您需要传递字符串的长度。您可以通过在 EAX 中获取结束地址并从中减去 source 指针来轻松地做到这一点。结果将是您遍历的字符串的长度。

修改代码为:

printString:
sub eax, source
invoke WriteConsoleA, consoleOutHandle, auxtarget, eax, bytesWritten, 0

您的代码版本遵循 C 调用约定,同时使用源缓冲区和目标缓冲区,测试指针以确保它们不为 NULL,使用类似的 method described by Peter Cordes 进行转换如下:

upperToLower proc uses edi esi, source:dword, dest:dword 
; uses ESI EDI is used to tell assembler we are clobbering two of
; the cdecl calling convetions non-volatile registers. See:
; https://en.wikipedia.org/wiki/X86_calling_conventions#cdecl
mov esi, source ; ESI = Pointer to string
test esi, esi ; Is source a NULL pointer?
jz done ; If it is then we are done

mov edi, dest ; EDI = Pointer to string
test edi, edi ; Is dest a NULL pointer?
jz done ; If it is then we are done

xor edx, edx ; EDX = 0 = current character index into the strings

jmp getnextchar ; Jump into loop at point of getting next character

charloop:
lea ecx, [eax - 'A'] ; cl = al-'A', and we do not care about the rest
; of the register

cmp cl, 25 ; if(c >= 'A' && c <= 'Z') c += 0x20;
lea ecx, [eax + 20h] ; without affecting flags
cmovna eax, ecx ; take the +0x20 version if it was in the
; uppercase range to start with
mov [edi + edx], al ; Update character in destination string
inc edx ; Go to next character

getnextchar:
movzx eax, byte ptr [esi + edx]
; mov al, [esi + edx] leaving high garbage in EAX is ok
; too, but this avoids a partial-register stall
; when doing the mov+sub
; in one instruction with LEA
test eax, eax ; Is the character NUL(0) terminator?
jnz charloop ; If not go back and process character

printString:
; EDI = source, EDX = length of string

invoke WriteConsoleA, consoleOutHandle, edi, edx, bytesWritten, 0
mov edx, sizeof buffer
done:
ret
upperToLower endp

采用一个参数并将源字符串更改为大写的版本可以这样完成:

upperToLower proc, source:dword
mov edx, source ; EDX = Pointer to string
test edx, edx ; Is it a NULL pointer?
jz done ; If it is then we are done

jmp getnextchar ; Jump into loop at point of getting next character

charloop:
lea ecx, [eax - 'A'] ; cl = al-'A', and we do not care about the rest
; of the register

cmp cl, 25 ; if(c >= 'A' && c <= 'Z') c += 0x20;
lea ecx, [eax + 20h] ; without affecting flags
cmovna eax, ecx ; take the +0x20 version if it was in the
; uppercase range to start with
mov [edx], al ; Update character in string
inc edx ; Go to next character

getnextchar:
movzx eax, byte ptr [edx] ; mov al, [edx] leaving high garbage in EAX is ok, too,
; but this avoids a partial-register stall
; when doing the mov+sub in one instruction with LEA
test eax, eax ; Is the character NUL(0) terminator?
jnz charloop ; If not go back and process character

printString:
sub edx, source ; EDX-source=length
invoke WriteConsoleA, consoleOutHandle, source, edx, bytesWritten, 0
done:
ret
upperToLower endp

观察

  • 执行字符串转换的通用 upperToLower 函数通常不会自行打印。您通常会调用 upperToLower 仅进行转换,然后在单独的调用中将字符串输出到显示器。

关于windows - 将字符串参数传递给 PROC,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57338869/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com