通过在线帮助,我能够在Mac OS X中编写nasm code,从而生成一个可执行文件,在同等的C代码中打印自己的文件名argv[0]
。当我在Windows中使用相同的代码时,我希望它打印程序名称:
C:\> nasm -f win32 -o scriptname.obj scriptname.asm
C:\> golink /fo scriptname.exe scriptname.obj /console kernel32.dll Msvcrt.dll
GoLink.Exe Version 0.27.0.0 - Copyright Jeremy Gordon 2002/12 - JG@JGnet.co.uk
Output file: scriptname.exe
Format: win32 size: 2,048 bytes
C:\> scriptname.exe
Program: scriptname.exe
但实际打印的是空虚:
C:\> scriptname.exe
Program:
规格:
答案 0 :(得分:2)
argc
和argv
参数仅适用于基于C的程序。基于程序集的程序必须使用C库中的__getmainargs
或__wgetmainargs
函数来生成这些变量,就像它们由基于C的程序在内部使用一样。有关详细信息,请参阅以下MSDN文章:
答案 1 :(得分:1)
您调用GetStdHandle并将返回的值保存到ecx,ecx是一个易失性寄存器,除非您按下/弹出它,否则不会在调用中保存该值。你对WriteConsoleA的第一次调用就是使用它,然后再次打电话给下一次调用,ecx不是你所期望的。
*编辑* 我很无聊所以这里是工作代码:
[bits 32]
section .data
program db "Program: ", 0
programlen equ $-program
nl db "", 13, 10, 0
nllen equ $-nl
section .bss
buf resd 1
argc resd 1
argv resb 255
section .text
global Start
extern GetStdHandle
extern __getmainargs
extern WriteConsoleA
extern ExitProcess
strlen: ; eax: a string ending in 0
push eax ; cache eax
.strloop:
mov bl, byte [eax]
cmp bl, 0
je .strret ; return len if bl == 0
inc eax ; else eax++
jmp .strloop
.strret:
pop ebx ; ebx = cached eax
sub eax, ebx ; eax -= ebx
ret ; eax = len
Start:
push 0
push buf
push argv
push argc
call __getmainargs
add esp, 16 ; clear stack (4 * 4 arguments)
push -11 ; get stdout
call GetStdHandle
mov esi, eax
add esp, 4 ; clear stack (4 * 1 argument)
push 0 ; null
push buf ; [chars written]
push programlen
push program
push esi ; stdout
call WriteConsoleA
add esp, 20 ; clear stack (4 * 5 arguments)
mov edx, [argv]
mov eax, [edx] ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
call strlen
push 0 ; null
push buf ; [chars written]
push eax ; len argv[0]
push dword [edx] ;<<<<<<<<<<<<<<<<<<<<<<<<<<<< ; argv[0]
push esi ; stdout
call WriteConsoleA
add esp, 20 ; clear stack (4 * 5 arguments)
push 0 ; null
push buf ; [chars written]
push nllen
push nl
push esi ; stdout
call WriteConsoleA
add esp, 20 ; clear stack (4 * 5 arguments)
push 0
call ExitProcess
D:\NASM Projects\ReadArgs>ReadArgs.exe
Program: ReadArgs.exe
D:\NASM Projects\ReadArgs>
答案 2 :(得分:0)
嗯,是的,不是。在Linux中,在_start:
标签处,argc
位于[esp]
,argv[0]
位于[esp + 4]
。如果您的代码有效,那么Mac OSX也必须如此。通过在ld命令行上执行-e main
,基本上main
就是它的名字。它不是真正的“C风格主力”。此标签被跳转到,而不是被称为。如果“C启动代码”(crt2.o)调用了main
(或_main,对于'doze和Mac OSX),则堆栈上有一个返回地址,因此argc
位于{{ 1}}和[esp + 4]
位于argv[0]
。另外,正如蒂姆在新闻中告诉你的那样:comp.lang.asm.x86 [esp + 8]
是一个argv
- 一个“指向指针的指针” - 所以你还需要**
(一个“de” -参考”)。我很确定在Windows中,无论我们将入口点命名为什么,都会调用我们的代码。你能以这种方式工作吗?
mov ebx, [ebx]