我目前正在开发一个小型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
系统写调用正在打印字符串,我需要它来打印整数。
有没有一些技巧可以做到这一点,还是我错过了一些明显的东西?
答案 0 :(得分:2)
您可以将整数转换为字符串,然后打印字符串(使用mov eax,4
... int 0x80
,就像现在一样),或者,您可以printf
使用{ {1}},需要call printf
(而非global main
),global start
,并与extern printf
进行关联。
关于如何将整数转换为十进制数字(字符串)的示例: How do I print an integer in Assembly Level Programming without printf from the c library?
如何在x86程序集中使用gcc
的示例:
nasm displaying a dword with printf
请注意,您需要 printf
或 extern printf
, extern _printf
或 global main
,具体取决于您的设置。
答案 1 :(得分: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
答案 2 :(得分: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
我希望这有助于将来遇到同样问题的其他人。