0

我目前正在开发一个小型 ASM 程序,该程序获取进程 ID,然后将其写出屏幕。

这是代码:

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,就像您现在所做的那样),或者,您可以使用printfwith call printf,它需要global main(而不是global start),extern printf并使用gcc.

有关如何将整数转换为十进制数(字符串)的示例: How do I print an integer in Assembly Level Programming without printf from the c library?

关于如何printf在 x86 程序集中使用的示例: nasm display a dword with printf

请注意,您需要 以及extern printf 具体取决于您的设置。extern _printf global main global _main

于 2013-03-14T20:28:42.220 回答
1

Linux 版本

这是 James Parker 的代码转换为在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

建造:

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 中的数字并将其用作转换表的索引,这将检索该整数的 ASCII 版本以用于 sys_write。

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 回答