문제

I'm currently working on a small ASM program that grabs the process ID and then writes it out the screen.

Here is the code:

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

My issue is that the program is printing the PID as a string and not an integer, too explain here is the same address displayed in GDB with different output formats.

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

The system write call is printing the string, and I need it to print the integer.

Is there some trick to do this, or am I missing something blatantly obvious?

도움이 되었습니까?

해결책 3

So I finally figured out the problem. Here is the solution for anyone that needs this in the future.

As a quick recap, the problem was taking the integer returned from the system call GET_PID and converting it to a string for use with SYS_WRITE.

The first step was to take the integer and isolate each digit; for example:

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

To achieve this I used the DIV function to divide the integer by 10, this leaves the remainder in EDX. If we look at the math 60015/10 would result in 6001.5, so the remainder 5 would be stored in EDX. A loop can then be used to retrieve each integer until it reaches zero, followed by a JZ to exit the loop.

The next step is to take each integer and find its ASCII code to store into a buffer. To do this, a translation table is used:

LookUpDig db "0123456789"

Take the digit stored in EDX and use it as an index into the translation table, this will retrieve the ASCII version of that integer for use with sys_write.

mov cl, [LookUpDig+edx]

Take the ASCII value and insert it into the buffer for the result.

mov [ebp], cl

Place this into the loop to build the string from the integer returned.

The full program should give more context to the solution, I hope the comments are detailed enough to explain each line of code.

;*************************************************************
; 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

I hope this helps anyone else out in the future who has the same issue.

다른 팁

You can either convert your integer to string and then print the string (with mov eax,4 ... int 0x80, as you do now), or, you can use printf with call printf, which needs global main (instead of global start), extern printf, and doing the linking with gcc.

An example on how to convert an integer into a decimal number (a string): How do I print an integer in Assembly Level Programming without printf from the c library?

An example on how to use printf in x86 assembly: nasm displaying a dword with printf

Note that you need either extern printf or extern _printf, and either global main or global _main, depending on your setup.

Linux Version

Here is a version of James Parker's code converted to run on x86/x86_64 Linux.

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

build:

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

output:

$ prnpid_32
PID: 1387
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top