gpt4 book ai didi

windows - NASM ReadConsoleA 或 WriteConsoleA 缓冲区调试问题

转载 作者:可可西里 更新时间:2023-11-01 11:51:17 33 4
gpt4 key购买 nike

我正在 Windows 上编写一个 NASM 汇编程序,让用户输入两个单位数字,将它们相加,然后输出结果。我正在尝试使用 Windows API 进行输入和输出。

不幸的是,虽然我可以让它在程序循环后立即读取一个数字以获得第二个值,但程序结束而不是要求第二个值。

程序的输出如下所示:

enter image description here

有趣的是,如果我输入 1,那么显示的值会大一个,所以它正在添加一些东西!

enter image description here

这也适用于输入的其他个位数 (2-9)。

我很确定这与我使用 ReadConsoleA 函数的方式有关,但我在尝试寻找解决方案时遇到了一些障碍。我安装了gdb来调试程序,组装如下:

  • nasm -f win64 -g -o task9.obj task9.asm
  • GoLink/console/entry _main task9.obj kernel32.dll
  • gdb task9

enter image description here

但我只是得到以下错误:

  • “C:\Users\Administrator\Desktop/task9.exe”:不是可执行格式:无法识别文件格式

我后来读到 NASM 不输出 Win64 格式所需的调试信息,但我对此不是 100% 确定。我相当确定我安装了 64 位版本的 GDB:

enter image description here

我的程序如下:

extern ExitProcess                          ;windows API function to exit process
extern WriteConsoleA ;windows API function to write to the console window (ANSI version)
extern ReadConsoleA ;windows API function to read from the console window (ANSI version)
extern GetStdHandle ;windows API to get the for the console handle for input/output

section .data ;the .data section is where variables and constants are defined

STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10

digits db '0123456789' ;list of digits

input_message db 'Please enter your next number: '
length equ $-input_message

section .bss ;the .bss section is where space is reserved for additional variables

input_buffer: resb 2 ;reserve 64 bits for user input

char_written: resb 4
chars: resb 1 ;reversed for use with write operation

section .text ;the .text section is where the program code goes

global _main ;tells the machine which label to start program execution from

_num_to_str:
cmp rax, 0 ;compare value in rax to 0
jne .convert ;if not equal then jump to label
jmp .output

.convert:
;get next digit value
inc r15 ;increment the counter for next digit

mov rcx, 10
xor rdx, rdx ;clear previous remainder result
div rcx ;divide value in rax by value in rcx
;quotient (result) stored in rax
;remainder stored in rdx

push rdx ;store remainder on the stack

jmp _num_to_str

.output:
pop rdx ;get the last digit from the stack

;convert digit value to ascii character
mov r10, digits ;load the address of the digits into rsi
add r10, rdx ;get the character of the digits string to display

mov rdx, r10 ;digit to print
mov r8, 1 ;one byte to be output

call _print

;decide whether to loop
dec r15 ;reduce remaining digits (having printed one)
cmp r15, 0 ;are there digits left to print?
jne .output ;if not equal then jump to label output

ret

_print:
;get the output handle
mov rcx, STD_OUTPUT_HANDLE ;specifies that the output handle is required
call GetStdHandle ;returns value for handle to rax

mov rcx, rax
mov r9, char_written

call WriteConsoleA

ret

_read:
;get the input handle
mov rcx, STD_INPUT_HANDLE ;specifies that the input handle is required
call GetStdHandle

;get value from keyboard
mov rcx, rax ;place the handle for operation

mov rdx, input_buffer ;set name to receive input from keyboard

mov r8, 2 ;max number of characters to read
mov r9, chars ;stores the number of characters actually read

call ReadConsoleA


movzx r12, byte[input_buffer]

ret

_get_value:
mov rdx, input_message ;move the input message into rdx for function call
mov r8, length ;load the length of the message for function call

call _print
xor r8, r8
xor r9, r9
call _read
.end:
ret

_main:
mov r13, 0 ;counter for values input
mov r14, 0 ;total for calculation
.loop:
xor r12, r12
call _get_value ;get value from user

sub r12, '0' ;convert char to integer
add r14, r12 ;add value to total

;decide whether to loop for another character or not
inc r13
cmp r13, 2
jne .loop

;convert total to ASCII value

mov rax, r14 ;num_to_str expects total in rax

mov r15, 0 ;num_to_str uses r15 as a counter - must be initialised
call _num_to_str

;exit the program
mov rcx, 0 ;exit code
call ExitProcess

如果您能在解决问题或如何使用 gdb 解决问题方面提供任何帮助,我将不胜感激。

最佳答案

我发现您的代码存在以下问题:

  1. > Microsoft x86-64 convention要求 rsp 为 16 字节对齐。
  2. 您必须在堆栈上为参数保留空间,即使您在寄存器中传递它们也是如此。
  3. 您的 chars 变量需要 4 个字节而不是 1 个字节。
  4. ReadConsole 需要 5 个参数。
  5. 您应该读取 3 个字节,因为 ReadConsole 返回 CR LF。或者您可以忽略前导空格。
  6. 如果输入是 0,您的 _num_to_str 就会损坏。

关于windows - NASM ReadConsoleA 或 WriteConsoleA 缓冲区调试问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29081694/

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