X64 Windows NASM汇编代码在ReadConsole上给出了细分故障,这可能是由于堆栈对齐问题引起的
我正在Windows X64汇编中编写质数生成器。现在,我一直坚持要获得一个数字的用户输入以生成质数,直到为止。这被视为字符串,稍后将转换为int
。
当前,下面的代码一旦我以ReadConsole函数进入控制台(使用gdb
),就会导致分割故障。
bits 64 ; Tell nasm to make 64-bit code
default rel ; Tell nasm to use rip-relative addressing. (Instruction pointer relative).
global main ; Export this
; Import these
extern printf
extern getchar
extern scanf
extern ExitProcess
extern GetStdHandle
extern ReadConsoleA
segment .bss ; uninitialised mutable data.
; resb - "reserve byte"
chartest: resb 1 ; char is 1 bytes
towhatnumberresponse: resb 4 ; reserve an int with name towhatnumberresponse
consoleinputhandle: resb 8 ; windows needs this for dumb reasons.
intstringread: resb 10 ; string read from console
intstring_as_int: resb 4 ; and converted to int stored here.
segment .data ; initialised read/write data.
STD_INPUT_HANDLE equ -10
NULL equ 0
printint db "%d", 0xd, 0xa, 0x0 ; 0xd, 0xa is the CRLF line terminator
printchar db "%c", 0xd, 0xa, 0x0
printstring db "%s %s, %s, %s", 0xd, 0xa, 0x0
genorcheck db "Would you like to generate prime numbers (G) or check if a number is prime (C)? ", 0x0
towhatnumber db "To what number would you like to generate primes to? ", 0x0
gentowhatnuminput db "%6d", 0x0
segment .text ; Where code is
; Function initialisation where we 'allocate' the shadow space required by
; Windows. Refer to https://sonictk.github.io/asm_tutorial/#windows:thewindowtothehardware/themicrosoftx64callingconvention/theshadowspace
push rbp
mov rbp, rsp
sub rsp, 32
lea rcx, [genorcheck] ; print genorcheck
call printf
xor rcx, rcx
call getchar
cmp rax, 'G' ; no ignoring here pls, compare with rax instead.
je generate_primes ; jump if equal (rax with 'G')
cmp rax, 'C'
je check_prime_num
; if none of G or C, then exit
add rsp, 32
pop rbp
ret
generate_primes:
push rbp
mov rbp, rsp
sub rsp, 64
lea rcx, [towhatnumber] ; printf(towhatnumber);
call printf
mov rcx, STD_INPUT_HANDLE ; value of -10
call GetStdHandle
mov [consoleinputhandle], QWORD rax ; store handle into consoleinputhandle
mov rcx, rax ; hConsoleInput
lea rdx, [intstringread] ; lpBuffer
mov r8, 9 ; nNumberOfCharsToRead. 1 less than space for a zero
mov r9, NULL ; lpNumberOfCharsRead: useless
push NULL ; pInputControl: unneeded.
call ReadConsoleA ; segfault when input is given after this call.
; just refer to this for anything
; https://github.com/jacwil/nasm-on-windows/blob/master/01_helloworld/win64/hello64.asm
cmp rax, 0 ; ReadConsoleA only returns 0 on error, non-zero otherwise
je error ; just sets return value to 20 and exits.
lea rcx, [intstringread]
call printf
lea rcx, [printstring]
lea rdx, [intstringread]
xor rax, rax
add rsp, 64
pop rbp,
ret
check_prime_num:
jmp exit
exit:
xor rcx, rcx ; ExitProcess(0) signals success
call ExitProcess
error:
mov rcx, 20
call ExitProcess
我认为问题可能是由于堆栈对齐问题引起的,或者没有给出足够的堆栈空间,但是我根本无法掌握这个概念(尽管有4天的阅读理论)。我已经检查了gcc -s
示例C程序的输出:
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <winbase.h>
char intasstring[11] = {0};
char buf[7] = {0};
void G();
int main(void)
{
G();
return 0;
}
void G() {
printf("To what number? ");
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &buf, 6, NULL, NULL);
printf("%s", intasstring);
}
它使用了
sub rsp, 80
我尝试但没有更改任何内容的方法。任何帮助都将不胜感激,因为我花了2天的时间试图解决这个问题。
segfault拆卸:
0x00007ffc696fe4c5 ? mov DWORD PTR [r15],eax
0x00007ffc696fe4c8 ? test r14b,r14b
0x00007ffc696fe4cb ? je 0x7ffc696fe4de <ReadConsoleA+494>
0x00007ffc696fe4cd ? shr eax,1
0x00007ffc696fe4cf ? mov DWORD PTR [r15],eax
0x00007ffc696fe4d2 ? test rbx,rbx
0x00007ffc696fe4d5 ? je 0x7ffc696fe4de <ReadConsoleA+494>
0x00007ffc696fe4d7 ? mov eax,DWORD PTR [rsp+0x64]
0x00007ffc696fe4db ? mov DWORD PTR [rbx+0xc],eax
0x00007ffc696fe4de ? cmp ecx,0x101
此时注册信息:
rax 0x0000000000000001 rbx 0x0000000000000000
rcx 0x0000000000000000 rdx 0x0000000000000000
rsi 0x0000000000000009 rdi 0x0000000000000011
rbp 0x000000e650dffd08 rsp 0x000000e650dffb38
r8 0x000000e650dff9d0 r9 0x000000e650dffad8
r10 0x0000000000000000 r11 0x0000000000000246
r12 0x00007ff7e7e3300d r13 0x00000000000001a4
r14 0x0000000000000000 r15 0x0000000000000000
rip 0x00007ffc696fe4c5
I am writing a prime number generator in Windows x64 assembly. Right now I am stuck at getting user input of a number to generate prime numbers until. This is taken as a string and will be converted into an int
later.
Currently the code below causes a Segmentation Fault as soon as I enter a character into the console at the ReadConsole function (using gdb
).
bits 64 ; Tell nasm to make 64-bit code
default rel ; Tell nasm to use rip-relative addressing. (Instruction pointer relative).
global main ; Export this
; Import these
extern printf
extern getchar
extern scanf
extern ExitProcess
extern GetStdHandle
extern ReadConsoleA
segment .bss ; uninitialised mutable data.
; resb - "reserve byte"
chartest: resb 1 ; char is 1 bytes
towhatnumberresponse: resb 4 ; reserve an int with name towhatnumberresponse
consoleinputhandle: resb 8 ; windows needs this for dumb reasons.
intstringread: resb 10 ; string read from console
intstring_as_int: resb 4 ; and converted to int stored here.
segment .data ; initialised read/write data.
STD_INPUT_HANDLE equ -10
NULL equ 0
printint db "%d", 0xd, 0xa, 0x0 ; 0xd, 0xa is the CRLF line terminator
printchar db "%c", 0xd, 0xa, 0x0
printstring db "%s %s, %s, %s", 0xd, 0xa, 0x0
genorcheck db "Would you like to generate prime numbers (G) or check if a number is prime (C)? ", 0x0
towhatnumber db "To what number would you like to generate primes to? ", 0x0
gentowhatnuminput db "%6d", 0x0
segment .text ; Where code is
; Function initialisation where we 'allocate' the shadow space required by
; Windows. Refer to https://sonictk.github.io/asm_tutorial/#windows:thewindowtothehardware/themicrosoftx64callingconvention/theshadowspace
push rbp
mov rbp, rsp
sub rsp, 32
lea rcx, [genorcheck] ; print genorcheck
call printf
xor rcx, rcx
call getchar
cmp rax, 'G' ; no ignoring here pls, compare with rax instead.
je generate_primes ; jump if equal (rax with 'G')
cmp rax, 'C'
je check_prime_num
; if none of G or C, then exit
add rsp, 32
pop rbp
ret
generate_primes:
push rbp
mov rbp, rsp
sub rsp, 64
lea rcx, [towhatnumber] ; printf(towhatnumber);
call printf
mov rcx, STD_INPUT_HANDLE ; value of -10
call GetStdHandle
mov [consoleinputhandle], QWORD rax ; store handle into consoleinputhandle
mov rcx, rax ; hConsoleInput
lea rdx, [intstringread] ; lpBuffer
mov r8, 9 ; nNumberOfCharsToRead. 1 less than space for a zero
mov r9, NULL ; lpNumberOfCharsRead: useless
push NULL ; pInputControl: unneeded.
call ReadConsoleA ; segfault when input is given after this call.
; just refer to this for anything
; https://github.com/jacwil/nasm-on-windows/blob/master/01_helloworld/win64/hello64.asm
cmp rax, 0 ; ReadConsoleA only returns 0 on error, non-zero otherwise
je error ; just sets return value to 20 and exits.
lea rcx, [intstringread]
call printf
lea rcx, [printstring]
lea rdx, [intstringread]
xor rax, rax
add rsp, 64
pop rbp,
ret
check_prime_num:
jmp exit
exit:
xor rcx, rcx ; ExitProcess(0) signals success
call ExitProcess
error:
mov rcx, 20
call ExitProcess
I think the problem may be due to stack alignment issues or not giving enough stack space but I just can't get my head around this concept at all (despite 4 days of reading theory). I've checked gcc -S
output of an example C program:
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <winbase.h>
char intasstring[11] = {0};
char buf[7] = {0};
void G();
int main(void)
{
G();
return 0;
}
void G() {
printf("To what number? ");
ReadConsole(GetStdHandle(STD_INPUT_HANDLE), &buf, 6, NULL, NULL);
printf("%s", intasstring);
}
and it used
sub rsp, 80
which I tried but didn't change anything. Any help would be appreciated as I've spent 2 days trying to figure this out.
Disassembly at Segfault:
0x00007ffc696fe4c5 ? mov DWORD PTR [r15],eax
0x00007ffc696fe4c8 ? test r14b,r14b
0x00007ffc696fe4cb ? je 0x7ffc696fe4de <ReadConsoleA+494>
0x00007ffc696fe4cd ? shr eax,1
0x00007ffc696fe4cf ? mov DWORD PTR [r15],eax
0x00007ffc696fe4d2 ? test rbx,rbx
0x00007ffc696fe4d5 ? je 0x7ffc696fe4de <ReadConsoleA+494>
0x00007ffc696fe4d7 ? mov eax,DWORD PTR [rsp+0x64]
0x00007ffc696fe4db ? mov DWORD PTR [rbx+0xc],eax
0x00007ffc696fe4de ? cmp ecx,0x101
Register info at this point:
rax 0x0000000000000001 rbx 0x0000000000000000
rcx 0x0000000000000000 rdx 0x0000000000000000
rsi 0x0000000000000009 rdi 0x0000000000000011
rbp 0x000000e650dffd08 rsp 0x000000e650dffb38
r8 0x000000e650dff9d0 r9 0x000000e650dffad8
r10 0x0000000000000000 r11 0x0000000000000246
r12 0x00007ff7e7e3300d r13 0x00000000000001a4
r14 0x0000000000000000 r15 0x0000000000000000
rip 0x00007ffc696fe4c5
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论