Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 如何在不将数据存储到变量nasm的情况下使用printf?_Windows_Assembly_X86_Nasm - Fatal编程技术网

Windows 如何在不将数据存储到变量nasm的情况下使用printf?

Windows 如何在不将数据存储到变量nasm的情况下使用printf?,windows,assembly,x86,nasm,Windows,Assembly,X86,Nasm,我试图在程序集中打印字符串,而不必将数据存储到变量中 工作原理: 现在,我想要的是将AAAA直接推送到堆栈并调用printf来打印它,而不必将它存储在消息中 我花了好几个小时用不同的方法尝试自己去做,但到目前为止失败了 尝试: 方法1: push 41414141h call _printf 方法2: mov esi, 41414141h push esi call _printf 方法3: mov esi, 41414141h mov edi, 7325 ; '%s' c

我试图在程序集中打印字符串,而不必将数据存储到变量中

工作原理:

现在,我想要的是将AAAA直接推送到堆栈并调用printf来打印它,而不必将它存储在消息中

我花了好几个小时用不同的方法尝试自己去做,但到目前为止失败了

尝试:

方法1:

push 41414141h
call _printf
方法2:

mov esi, 41414141h
push esi
call _printf
方法3:

mov   esi, 41414141h
mov   edi, 7325      ; '%s'
call  _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
方法4:

mov   esi, 41414141h
mov   edi, 7325      ; '%s'
push  esi
push  edi
call  _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
方法5:

mov   esi, 41414141h
mov   edi, 7325      ; '%s'
push  esi
xor   eax, eax
push  eax            ; just push a null byte to the stack
push  edi
call  _printf
; or storing 'AAAA' in EDI and storing '%s' in ESI
还有很多我都不记得了

那么,打印存储在寄存器中的值的正确方法是什么呢

如果可以回答下面的问题,我将不胜感激

在调查了第一次尝试是如何工作的之后。我意识到,数据或AAAA存储在程序堆栈中,然后数据的地址被推送到ESP

不幸的是,我不知道如何将数据推送到程序的stack\.data部分,或者如果可能的话,以及如何将该部分的地址推送到ESP。

我不习惯使用_printf函数,但我可以向您展示如何通过syscall做到这一点:

mov dword [esp-4], 'AAAA' ; This is the red-zone, try googling it
    
; The actual printing
mov eax, 4
mov ebx, 1
lea ecx, [esp-4]
mov edx, 4
int 80h
顺便说一下,它使用Linux 32位系统调用,但不确定windows系统调用是什么

也许试着按一下[esp-4]

[编辑]忘了提到这一点的一个主要限制,至少在系统调用中是这样,但仍然不确定\u printf最多只能打印4个字符,不能再打印了。
[另一个编辑]正如其他评论者所指出的,这种方法可能是不安全的检查评语,因此您可以决定避免它。

push 0;推41h;推动esp;调用_printf注意:您需要零终止字符串。您还需要删除放在堆栈上的内容。@Jester,您做得更好,效果很好:您的数据节版本只起作用,因为它后面正好有一些0填充。您应该使用db'AAAA',0来生成C字符串,或者使用fwrite和指针、长度,这样就不需要终止符。另外,通常您会将只读常量数据放在section.rodata中。请注意,在mov存储和系统调用读取数据之间,依靠ESP下面的数据保持不修改在技术上是不安全的。评估print foo的信号处理程序或调试器可以使用该堆栈空间。只有x86-64 System V ABI保证RSP下方的红色区域可以安全使用。在这种情况下,按“AAAA”键/mov ecx,esp将是一个更好的选择。re:您对以下问题的实际答案:mov dword[esp-4],“AAAA”键/push[esp-4]将不是一个好主意。这相当于推动“AAAA”;push[esp-4]基本上是一个NOP从同一位置加载并重新存储dword:从旧esp下方加载,然后在递减后存储到新esp。libc printf需要一个指向以0结尾的C字符串隐式长度的指针,这就是为什么没有4参数,而不是值。Windows cdecl调用约定或多或少与Linux i386 Sys V调用约定相匹配,因此您可以在Linux上使用call printf。感谢您提供的信息,我根据任何方式编辑了我的答案,如问题注释中所述,您可以推送终止0,然后推送一些字符串数据。ESP然后指向C字符串,因此您可以推送ESP/call printf。顺便说一句,与Linux不同,Windows的原始系统调用接口没有文档记录或不受支持,因此标准方法是使用WinAPI DLL函数调用。或者对DLL进行反向工程,直接在特定版本的Windows上进行原始系统调用。我认为32位Windows DLL最终会进行远程调用或跳转到64位用户空间以使用syscall,这与Linux syscenter相比似乎是一个很大的开销。我建议修复您的答案,以显示可以在堆栈上构造以0结尾的C字符串的内容。我投了反对票,因为这没有显示任何调用printf的有用信息。Linux sys_write作为Windows问题的答案并不是特别有用,而Linux Q&as已经证明了这一点。如果这个答案有所改善,我很乐意取消或取消我的否决票,特别是修正推[esp-4]可能会有帮助的建议。如果您的意思是LEA/push,那么请记住push将覆盖[esp-4]中的任何内容,因为它执行esp-=4和[esp]=src。
mov dword [esp-4], 'AAAA' ; This is the red-zone, try googling it
    
; The actual printing
mov eax, 4
mov ebx, 1
lea ecx, [esp-4]
mov edx, 4
int 80h