在 FASM 中调用 _getch 之前无法弄清楚我必须将什么推入堆栈
Can't figure out what I must I push to the stack before calling `_getch` in FASM
我正在使用 SASM IDE by Dmitry Manushin 在 FASM 中编写程序。我的代码如下:
format ELF
section '.data' writeable
msg db 'Hello, world of Flat ASM!', 0Dh, 0Ah, 00h ; terminate with null string
buffer rb 20
inp_buf_size rw 1
pkey db 'Press any key to exit ...', 0h
formatStr db "%s", 0
section '.text' executable
public _main
extrn _printf
extrn _getch
extrn _getche
_main:
mov ebp, esp; for correct debugging
push msg ; push message onto the stack
push formatStr ; push formatter onto the stack
call _printf ; call the printf method to print the message
add esp, 8 ; clean up
xor eax, eax
; press any key to exit
mov ebp, esp; for correct debugging
push pkey ; push message onto the stack
push formatStr ; push formatter onto the stack
call _printf ; call the printf method to print the message
add esp, 8
xor eax, eax
; get input here, using getch or getche (how? What must be pushed)
; mov ebp, esp; for correct debugging
; push buffer
; call _getch
; add esp, 8
; xor eax, eax
ret
按预期打印 "Hello, world ..." 和 "Press any key ..." 代码。我坚持的是如何让程序使用 _getch
等待 for/read 单个字符进入缓冲区。 (如果有的话,我应该在调用 _getch
之前将什么压入堆栈?)我尝试将值移入 ah
并使用中断,但这会导致程序崩溃。
- OS: Windows 10 x86_64
- 汇编语言: FASM(包含在 SASM 中)--
$SOURCE$ $PROGRAM.OBJ$ -s $LSTOUTPUT$
- ** 模式:** x86
- 链接器选项:
$PROGRAM.OBJ$ $MACRO.OBJ$ -g -o $PROGRAM$ -m32
这里发生了一些事情 format ELF
告诉 FASM 创建一个 Linux 目标文件。这感觉有点奇怪,因为你是 运行 Windows。但让它起作用的是 SASM 使用 Linux gcc 工具链的 MinGW 版本来创建可执行文件。这意味着您可以编写一些 Linux 程序集,但并非所有内容都可以是 Linux 语法。
另一个问题是 getch
不是 POSIX,所以可能会导致问题,请改用 getchar
。
最后,windows 不会通过在 eax 中使用 return 值来退出程序。
xor eax, eax
ret
因此,部分将在 Windows 中挂起。一个安全的方法是 call _ExitProcess
在堆栈上传递 0。
似乎 SASM 期望任何输入都预先输入到输入框中,因此不会等待 _getchar
。我保留它是为了展示如果 SASM 不这样做它会如何工作。 运行 使用 FASM 直接组装的类似代码按预期工作。
把所有这些放在一起我们得到这个:
format ELF
section '.data' writeable
msg db 'Hello, world of Flat ASM!', 0Dh, 0Ah, 00h
pkey db 'Press any key to exit ...', 0h
formatStr db "%s", 0
public _main
extrn _printf
extrn _getchar
extrn _ExitProcess
section '.text' executable
_main:
push msg
push formatStr
call _printf
push pkey
push formatStr
call _printf
call _getchar
push 0
call _ExitProcess
为了简单起见,我删除了堆栈代码,因为这只是一个 hello world。
当我发现你的问题时,我实际上是在试图弄清楚如何让 SASM 在 Windows 上运行,在我写下我的其他答案后,我偶然发现了一种能够使用原生 Windows FASM 语法。在构建选项中,选中 "Disable linking" 框并将 $PROGRAM.OBJ$
"Assembly options" 参数更改为 $PROGRAM$
。这将导致它使用 Windows FASM.exe 到 assemble 你的 exe 并跳过 Linux 样式对象创建和 gcc 链接。
一个很大的负面影响是调试器不再工作,这对我来说是一个交易杀手。
为了展示 Windows FASM 代码的样子,这是我的 hello world:
format PE console
entry _main
include '%fasm_inc%/win32a.inc'
section '.data' data readable
hello db 'Hello world!', 0
section '.text' code readable executable
_main:
invoke _printf, hello
invoke _getchar
push eax
invoke _putchar
invoke _ExitProcess, 0
section '.idata' import data readable
library kernel32, 'kernel32.dll',\
msvcrt, 'msvcrt.dll'
import kernel32,\
_ExitProcess, 'ExitProcess'
import msvcrt,\
_printf, 'printf',\
_getchar, 'getchar',\
_putchar, 'putchar'
我添加了 _putchar
以表明 _getchar
正在使用输入框中的文本并且 SASM 不等待用户输入。
我正在使用 SASM IDE by Dmitry Manushin 在 FASM 中编写程序。我的代码如下:
format ELF
section '.data' writeable
msg db 'Hello, world of Flat ASM!', 0Dh, 0Ah, 00h ; terminate with null string
buffer rb 20
inp_buf_size rw 1
pkey db 'Press any key to exit ...', 0h
formatStr db "%s", 0
section '.text' executable
public _main
extrn _printf
extrn _getch
extrn _getche
_main:
mov ebp, esp; for correct debugging
push msg ; push message onto the stack
push formatStr ; push formatter onto the stack
call _printf ; call the printf method to print the message
add esp, 8 ; clean up
xor eax, eax
; press any key to exit
mov ebp, esp; for correct debugging
push pkey ; push message onto the stack
push formatStr ; push formatter onto the stack
call _printf ; call the printf method to print the message
add esp, 8
xor eax, eax
; get input here, using getch or getche (how? What must be pushed)
; mov ebp, esp; for correct debugging
; push buffer
; call _getch
; add esp, 8
; xor eax, eax
ret
按预期打印 "Hello, world ..." 和 "Press any key ..." 代码。我坚持的是如何让程序使用 _getch
等待 for/read 单个字符进入缓冲区。 (如果有的话,我应该在调用 _getch
之前将什么压入堆栈?)我尝试将值移入 ah
并使用中断,但这会导致程序崩溃。
- OS: Windows 10 x86_64
- 汇编语言: FASM(包含在 SASM 中)--
$SOURCE$ $PROGRAM.OBJ$ -s $LSTOUTPUT$
- ** 模式:** x86
- 链接器选项:
$PROGRAM.OBJ$ $MACRO.OBJ$ -g -o $PROGRAM$ -m32
这里发生了一些事情 format ELF
告诉 FASM 创建一个 Linux 目标文件。这感觉有点奇怪,因为你是 运行 Windows。但让它起作用的是 SASM 使用 Linux gcc 工具链的 MinGW 版本来创建可执行文件。这意味着您可以编写一些 Linux 程序集,但并非所有内容都可以是 Linux 语法。
另一个问题是 getch
不是 POSIX,所以可能会导致问题,请改用 getchar
。
最后,windows 不会通过在 eax 中使用 return 值来退出程序。
xor eax, eax
ret
因此,部分将在 Windows 中挂起。一个安全的方法是 call _ExitProcess
在堆栈上传递 0。
似乎 SASM 期望任何输入都预先输入到输入框中,因此不会等待 _getchar
。我保留它是为了展示如果 SASM 不这样做它会如何工作。 运行 使用 FASM 直接组装的类似代码按预期工作。
把所有这些放在一起我们得到这个:
format ELF
section '.data' writeable
msg db 'Hello, world of Flat ASM!', 0Dh, 0Ah, 00h
pkey db 'Press any key to exit ...', 0h
formatStr db "%s", 0
public _main
extrn _printf
extrn _getchar
extrn _ExitProcess
section '.text' executable
_main:
push msg
push formatStr
call _printf
push pkey
push formatStr
call _printf
call _getchar
push 0
call _ExitProcess
为了简单起见,我删除了堆栈代码,因为这只是一个 hello world。
当我发现你的问题时,我实际上是在试图弄清楚如何让 SASM 在 Windows 上运行,在我写下我的其他答案后,我偶然发现了一种能够使用原生 Windows FASM 语法。在构建选项中,选中 "Disable linking" 框并将 $PROGRAM.OBJ$
"Assembly options" 参数更改为 $PROGRAM$
。这将导致它使用 Windows FASM.exe 到 assemble 你的 exe 并跳过 Linux 样式对象创建和 gcc 链接。
一个很大的负面影响是调试器不再工作,这对我来说是一个交易杀手。
为了展示 Windows FASM 代码的样子,这是我的 hello world:
format PE console
entry _main
include '%fasm_inc%/win32a.inc'
section '.data' data readable
hello db 'Hello world!', 0
section '.text' code readable executable
_main:
invoke _printf, hello
invoke _getchar
push eax
invoke _putchar
invoke _ExitProcess, 0
section '.idata' import data readable
library kernel32, 'kernel32.dll',\
msvcrt, 'msvcrt.dll'
import kernel32,\
_ExitProcess, 'ExitProcess'
import msvcrt,\
_printf, 'printf',\
_getchar, 'getchar',\
_putchar, 'putchar'
我添加了 _putchar
以表明 _getchar
正在使用输入框中的文本并且 SASM 不等待用户输入。