0

オンラインヘルプを使用して、Mac OS Xでnasmコードargv[0]を記述し、同等のCコードで独自のファイル名を出力する実行可能ファイルを作成することができました。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: 

仕様:

  • golink 0.27.0.0
  • nasm 2.10.05
  • Windows 7 Professional x64
  • MacBook Pro 2009
4

3 に答える 3

2

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>
于 2012-10-08T02:08:10.660 に答える
2

および引数はargcargvC ベースのプログラム専用です。アセンブリ ベースのプログラムは、C ライブラリの関数__getmainargsまたは__wgetmainargs関数を使用して、C ベースのプログラムによって内部的に使用されるような変数を生成する必要があります。詳細については、以下の MSDN 記事を参照してください。

http://msdn.microsoft.com/en-us/library/ff770599.aspx

于 2012-10-07T07:36:34.167 に答える
0

はい、いいえ。Linux では、_start:ラベルで、argcis at[esp]およびargv[0]at[esp + 4]です。コードが機能する場合、これは Mac OSX にも当てはまります。-e mainld コマンドラインで行うことにより、本質的mainにその名前について嘘をついています。それは実際には「Cスタイルのメイン」ではありません。このラベルは、呼び出されるのではなく、ジャンプされます。(または 'doze および Mac OSX の場合mainは _main) が「C スタートアップ コード」(crt2.o) によって呼び出される場合、スタックに戻りアドレスがあるため、argcat[esp + 4]およびargv[0]at[esp + 8]です。また、ティムが news:comp.lang.asm.x86 であなたに言っているようにargv**「ポインターへのポインター」なので、mov ebx, [ebx](「逆参照」)。Windows では、エントリポイントの名前に関係なくコードが呼び出されると確信しています。そのように機能させることができますか?

編集: まあ、これはほとんど殴り殺され、「解決」(?) されましたが、私も退屈しました。これは Linux で動作し、「おそらく」移植可能です。

;  prints its own name (possibly portable?)
; nasm -f elf32 myprog.asm
; nasm -f macho myprog.asm --prefix _
; nasm -f win32 myprog.asm --prefix _
; gcc -o myprog myprog.o(bj) (-m32 for 64-bit  systems)

global main
extern printf

section .data
    prog db `Program: %s \n`, 0

section .text
main:
    mov eax, [esp + 8]
    mov eax, [eax]
    push eax
    push prog
    call printf
    add esp, 4 * 2
    ret
;----------------------
于 2012-10-07T18:20:27.760 に答える