我正在尝试将整数转换为字符串,然后使用 MessageBoxA 函数显示它。如果数字是 xero 则成功,但任何其他正整数都会显示为空白弹出消息。
default rel
global WinMain
extern ExitProcess
extern MessageBoxA
section .data
title: db 'Melang64', 0
section .bss
buf: resb 80
section .text
WinMain:
sub rsp, 28h
mov rax, buf
mov rdi, 1
call uitoa
mov rcx, 0
lea rdx,[buf]
lea r8,[title]
mov r9d, 0
call MessageBoxA
mov ecx,eax
call ExitProcess
add rsp, 28h
hlt
uitoa:
mov rsi, rax
mov rax, rdi
cmp rax,0
jnz uitoa_convert_nrm
mov byte [rsi], 48
inc esi
mov byte [rsi], 0
jmp uitoa_end
uitoa_convert_nrm:
mov r10, 10
xor rcx, rcx
uitoa_loop:
xor rdx, rdx
div r10
inc ecx
cmp rax, 0
jnz uitoa_loop
inc ecx
add rsi, rcx
mov byte [rsi], 0
mov rax, rdi
dec ecx
uitoa_convert:
xor rdx, rdx
dec rsi
div r10
add rdx, 48
mov byte [rsi], dl
loopnz uitoa_convert
uitoa_end:
ret
我使用以下程序来运行此代码,它是一个 C++ 程序,只需将命令发送到命令提示符以创建 obj 文件,链接它,然后运行 exe:
#include <cstdlib>
#include <windows.h>
#include <iostream>
#include <string>
int main() {
std::cout << "Hello\n";
system("nasm -f win64 Hi.asm");
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi;
const wchar_t* command = L"\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\bin\\Hostx64\\x64\\link.exe\" Hi.obj /subsystem:windows /entry:WinMain /libpath:\"C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Tools\\MSVC\\14.38.33130\\lib\\x64\" /nodefaultlib msvcrt.lib /libpath:\"C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.22621.0\\um\\x64\" /nodefaultlib kernel32.lib user32.lib /largeaddressaware:no";
std::wstring writableCommand(command);
if (CreateProcess(NULL, &writableCommand[0], NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
else {
std::wcerr << L"Error: " << GetLastError() << std::endl;
}
system("Hi.exe");
return 0;
}
C++ 程序不是问题,但是我相信将整数转换为字符串的 asm 部分是问题。
我使用的是nasm,我使用的是windows机器。我正在为 64 位编写。
我的汇编知识不是最好的,但我尽力确保所有寄存器以及函数调用都是正确的。该程序运行完美,只是没有显示应有的数字,并且在代码上下文中显示空白消息或缓冲区。
你的2系列除法的方法是低效,但它是正确的除了你把终止零一个字节放得太远。因此,Windows 在您提供的缓冲区中看到一个空字符串。
目前将数字1转换得到的是:
0, '1', 0
^
buf
uitoa:
mov rsi, rax
mov rax, rdi
cmp rax,0
jnz uitoa_convert_nrm
mov byte [rsi], 48
inc esi
mov byte [rsi], 0
jmp uitoa_end
uitoa_convert_nrm:
mov r10, 10
xor rcx, rcx
uitoa_loop:
xor rdx, rdx
div r10
inc ecx
cmp rax, 0
jnz uitoa_loop
inc ecx <<<<<<< Remove this line!
add rsi, rcx
mov byte [rsi], 0
mov rax, rdi
dec ecx <<<<<<< Remove this line too!
uitoa_convert: RCX is at least 1 at this point
xor rdx, rdx
dec rsi
div r10
add rdx, 48
mov byte [rsi], dl
loopnz uitoa_convert <<<<<<< Just use LOOP (still inefficient)
uitoa_end:
ret