我刚刚开始使用ASM(NASM),需要一些关于以下代码段的帮助。我没有错误/警告,它只是没有输出任何东西。我期待的是它获得时间(13),然后打印出(4),然后退出(1)。另外,有没有人知道一些好的(最好是NASM特定的)ASM教程?
section .bss
time: resb 255
section .text
global _start
_start:
mov eax, 13
int 0x80
mov eax, time
mov edx, 255
mov ecx, time
mov ebx, 1
mov eax, 4
int 0x80
mov eax, 1
int 0x80
答案 0 :(得分:6)
这里的第一个问题是您需要了解sys_time sys调用。在http://syscalls.kernelgrok.com/有一个方便的图表,它告诉你各种sys调用在寄存器中需要输入的内容。
sys_time是系统调用13,所以
mov eax,13
很好
然而,sys_time还需要在ebx中传递一个内存地址,它会写入实际时间。
快速的方法是在堆栈上分配一些空间(我们可以在堆栈上推送任何内容,sys_time值将覆盖它,为什么不将eax的值粘贴到它上面)。
push eax
然后将堆栈指针输入ebx
mov ebx, esp
现在进行系统调用
int 80h
现在我们可以将时间从堆栈中弹出(例如eax)
pop eax
现在eax包含当前的unix时间(即自1970年1月1日以来的秒数。)
为了避免将数字直接打印到unix控制台上的棘手问题,我将作弊并提供一个完整的示例,通过gcc编译nasm并与c库链接并使用printf
[SECTION .data]
PrintNum db "%d",10,0 ;this is a c string so is null terminated
[SECTION .text]
extern printf
global main
main:
push ebp
mov ebp,esp
push ebx
push esi
push edi ; stuff before this for glibc compatibility
mov eax, 13
push eax
mov ebx, esp
int 0x80
pop eax
push eax ; push eax onto stack then the format string, then call printf to write eax to console, unwind stack pointer
push PrintNum
call printf
add esp,8
pop edi ; stuff after this for glibc compatibility
pop esi
pop ebx
mov esp,ebp
pop ebp
ret
使用
进行编译nasm -f elf sys_time.asm
gcc sys-time.o -o sys-time
虽然如果您使用的是64位Linux,您可能需要这样做(并且具有相关的multilib gcc和glibc)。您无法将此程序编译为本机64位可执行文件,因为它使用push和pop而您无法将32位寄存器压入64位堆栈。
nasm -f elf32 sys_time.asm
gcc -m32 sys-time.o -o sys-time
然后你应该
$ ./systime
1310190574
我已经在32位和64位linux上测试了这个,并设法编译上面的代码。如果您有任何问题,请告诉我。
为了回答你的问题看过nasm教程,我最近从Jeff Duntemann的“汇编语言一步一步,第三版”中学习。有关详细信息和示例章节,请参阅http://www.duntemann.com/assembly.html。
答案 1 :(得分:3)
这是您转换为C的示例。您正在将时间指针复制到eax而不是eax到缓冲区。仍然这样做是行不通的,因为你想要一个char数组来写,而不是一个打印垃圾的原始整数。
#include <stdlib.h>
char b[255];
int
main()
{
/* You wanted to do this which doesn't work
* because write wont take int* but char arrays
* *(int*)b=time(NULL);
*/
/* Instead you did */
time(NULL);
b;
write(1, b, 255);
exit(1);
}