0

私は現在、プロセス ID を取得して画面に書き込む小さな ASM プログラムに取り組んでいます。

コードは次のとおりです。

SECTION .bss

    Pid: resb 4

SECTION .text

global start

start:
    mov eax, 0x14       ; System call 20 - Get PID
    push eax            ; Push to stack for BSD
    int 0x80            ; Call
    mov edx, eax        ; Save return value in EDX
    add esp, 0x4        ; Clean up the stack

    push 0x4            ; Push lenth of 4 bytes
    mov [Pid], edx      ; Move address to Pid Buffer
    push Pid
    push 0x1            ; Set file descriptor as 1 (stdout)
    mov eax, 0x4        ; Set system call 4 - Write
    push eax            ; Push the system call to stack
    int 0x80            ; Call
    add esp, 0x10       ; Clean up the stack

    mov eax, 1          ; Set call 1 - sys_exit
    mov ebx, 0          ; All went well
    int 0x80            ; Call

私の問題は、プログラムが PID を整数ではなく文字列として出力していることです。ここでも、GDB に表示される同じアドレスが異なる出力形式で表示されることを説明してください。

String:  0x2016 <Pid>:  "z\035"
Hex:     0x2016 <Pid>:  0x00001d7a
Integer: 0x2016 <Pid>:  7546

システム書き込み呼び出しは文字列を出力していますが、整数を出力する必要があります。

これを行うためのトリックはありますか、それとも明らかに明らかな何かが欠けていますか?

4

3 に答える 3

2

整数を文字列に変換してから文字列を出力するか(現在のようにmov eax,4...int 0x80を使用)、またはを使用printfして(の代わりに)、call printfを必要とし、を使用してリンクを行うことができます。global mainglobal startextern printfgcc

整数を10進数(文字列)に変換する方法の例: cライブラリからprintfを使用せずにアセンブリレベルプログラミングで整数を出力するにはどうすればよいですか?

printfx86アセンブリで の使用方法の例: printfでdwordを表示するnasm

設定に応じて、またはのいずれ extern printf extern _printf、およびのいずれ かが必要であることに注意してください。global main global _main

于 2013-03-14T20:28:42.220 に答える
1

Linux版

x86/x86_64 Linuxで実行するように変換された James Parker のコードのバージョンを次に示します。

SECTION .data

    LookUpDig db "0123456789"             ; Translation Table
    PIDString db "PID: "
    PIDLength equ $-PIDString

SECTION .bss

    PID: resb 8                           ; Reserve space for result

SECTION .text

            global _start

    _start:
            mov     eax, 0x14             ; GET_PID call
            int     0x80                  ; Call
            mov     ebx, 0xA              ; Set divider to 10
            mov     ebp, PID+6            ; Save the address of PID+6 to EBP
            jnz     LoopMe                ; Run the loop to convert int to string

    LoopMe:
            div     ebx                   ; Divide the PID by 10
            mov     cl, [LookUpDig+edx]   ; Copy ASCII value to CL
            mov     [ebp], cl             ; Copy CL to PID buffer
            dec     ebp                   ; Move to next byte in the buffer
            xor     edx, edx              ; Clear the remainder, else weird results :)
            inc     eax                   ; Increase EAX tricking JNZ
            dec     eax                   ; Decrease to get back to original value
            jnz     LoopMe                ; Loop until EAX is zero (all integers converted)
            jz      PrintOut              ; When done call the print out function

    PrintOut:
            mov     edx, PIDLength        ; Push PIDString Length
            mov     ecx, PIDString        ; Push PIDString
            mov     ebx, 0x1              ; FD stdout
            mov     eax, 0x4              ; sys_write call
            int     0x80                  ; Call kernel

            mov     [PID+7], byte 0xA     ; Push a newline to PID string

            mov     edx, 0x8              ; Max length of 8 bytes
            mov     ecx, PID              ; Push PID value
            mov     ebx, 0x1              ; FD stdout
            mov     eax, 0x4              ; sys_write call
            int     0x80                  ; Call kernel

            mov     eax, 0x1              ; Set system_call
            xor     ebx,ebx               ; Exit_code 0
            int     0x80                  ; Call kernel

建てる:

nasm -f elf -o prnpid_32.o prnpid_32.asm
ld -o prnpid_32 prnpid_32.o                 # On native 32-bit machine
ld -m elf_i386 -o prnpid_32 prnpid_32.o     # On x86_64

出力:

$ prnpid_32
PID: 1387
于 2014-10-10T22:28:46.720 に答える
0

それで、私はついに問題を理解しました。これは、将来これを必要とする人のためのソリューションです。

簡単にまとめると、問題はシステム コール GET_PID から返された整数を取得し、それを SYS_WRITE で使用する文字列に変換することでした。

最初のステップは、整数を取得して各桁を分離することでした。例えば:

Returned PID: 60015 - Grab each integer own its own i.e. 5 1 0 0 6

これを実現するために、DIV 関数を使用して整数を 10 で割りました。これにより、残りが EDX に残されます。数学を見ると、60015/10 は 6001.5 になるので、残りの 5 は EDX に格納されます。その後、ループを使用してゼロになるまで各整数を取得し、続いて JZ を使用してループを終了できます。

次のステップでは、各整数を取得し、その ASCII コードを見つけてバッファーに格納します。これを行うには、変換テーブルが使用されます。

LookUpDig db "0123456789"

EDX に保存されている数字を取得し、変換テーブルへのインデックスとして使用します。これにより、sys_write で使用するためにその整数の ASCII バージョンが取得されます。

mov cl, [LookUpDig+edx]

ASCII 値を取得し、結果のバッファに挿入します。

mov [ebp], cl

これをループに配置して、返された整数から文字列を作成します。

完全なプログラムは、ソリューションにさらにコンテキストを提供する必要があります。コメントがコードの各行を説明するのに十分詳細であることを願っています。

;*************************************************************
; Date    : 02/04/2013                                       *
; Compile : nasm -f macho -o pid.o space.asm                 *
; Link    : ld -macosx_version_min 10.7 -o pid pid.o         *          
; Descr.  : Prints the process PID, could be used in a       *
;           larger program.                                  *
; Nasm v. : NASM version 0.98.40                             *
;*************************************************************

SECTION .data

    LookUpDig db "0123456789"         ; Translation Table
    PIDString db "PID: "
    PIDLength equ $-PIDString

SECTION .bss

    PID: resb 8                       ; Reserve space for result

SECTION .text

global start

start:
    mov eax, 0x14             ; GET_PID call
int 0x80                  ; Call  
mov ebx, 0xA              ; Set divider to 10
mov ebp, PID+6            ; Save the address of PID+6 to EBP
jnz LoopMe                ; Run the loop to convert int to string

LoopMe: 
div ebx                   ; Divide the PID by 10
mov cl, [LookUpDig+edx]   ; Copy ASCII value to CL
mov [ebp], cl             ; Copy CL to PID buffer
dec ebp                   ; Move to next byte in the buffer
xor edx, edx              ; Clear the remainder, leave in for some weird results :)
inc eax                   ; Increase EAX tricking JNZ
dec eax                   ; Decrease to get back to original value
jnz LoopMe                ; Keep looping until EAX is zero (all integers converted)
jz PrintOut               ; When done call the print out function

PrintOut:
push PIDLength            ; Push PIDString Length
push PIDString            ; Push PIDString
push 0x1                  ; FD stdout
mov eax, 0x4              ; sys_write call
push eax                  ; Push call (BSD)
int 0x80                  ; Call
add esp, 0x10             ; Clear up the stack

mov [PID+7], byte 0xA     ; Push a newline to PID string

push 0x8                  ; Max length of 8 bytes
push PID                  ; Push PID value
push 0x1                  ; FD stdout
mov eax, 0x4              ; sys_write call
push eax                  ; Push call (BSD)
int 0x80                  ; Call
add esp, 0x10             ; Clean up stack

mov eax, 0x1              ; Set system_call
push 0x0                  ; Exit_code 0
int 0x80                  ; Call

これが、将来同じ問題を抱えている他の誰かに役立つことを願っています。

于 2013-04-03T14:15:56.250 に答える