Assembly NASM打印时间-代码不';我什么也不输出
我刚刚开始使用ASM(NASM),需要以下代码片段的帮助。我没有收到任何错误/警告,只是没有输出任何内容。我所期望的是它得到时间(13),然后打印出来(4),然后退出(1)。还有,有人知道一些好的(最好是NASM特定的)ASM教程吗Assembly NASM打印时间-代码不';我什么也不输出,assembly,nasm,Assembly,Nasm,我刚刚开始使用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
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
这是翻译成C的示例。您将指向时间的指针复制到eax,而不是eax到缓冲区。但这仍然不起作用,因为您需要用于写入的字符数组,而不是将打印垃圾的原始整数
#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);
}
#包括
字符b[255];
int
main()
{
/*你想这么做,但没用
*因为write不接受int*而接受char数组
**(int*)b=时间(空);
*/
/*相反,你做到了*/
时间(空);
B
写入(1,b,255);
出口(1);
}
这是您翻译为C的示例。您正在将指向时间的指针复制到eax,而不是将eax复制到缓冲区。但这仍然不起作用,因为您需要用于写入的字符数组,而不是将打印垃圾的原始整数
#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);
}
#包括
字符b[255];
int
main()
{
/*你想这么做,但没用
*因为write不接受int*而接受char数组
**(int*)b=时间(空);
*/
/*相反,你做到了*/
时间(空);
B
写入(1,b,255);
出口(1);
}
这里的第一个问题是您需要理解sys\u time sys调用。这里有一个方便的图表,告诉您各种sys调用需要什么作为寄存器中的输入
系统时间是系统调用13,所以
mov eax,13
很好
然而,sys_time还需要在ebx中传递一个内存地址,它在ebx中写入实际时间
一个快速的方法是在堆栈上分配一些空间(我们可以在堆栈上推送任何东西,sys_time值将覆盖它,为什么不将eax的值粘贴到它上)
然后将堆栈指针馈送到ebx
mov ebx, esp
现在进行系统调用
int 80h
现在,我们可以从堆栈中弹出时间(例如,eax)
现在eax包含当前unix时间(即自1970年1月1日起的秒数)
为了避免直接将数字打印到unix控制台的麻烦,我将作弊并提供一个完整的示例,该示例在nasm中编译,并通过gcc与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,您可能必须这样做(并拥有相关的多库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教程的问题,我最近学习了杰夫·邓特曼的“汇编语言分步学习,第三版”。有关详细信息和示例章节,请参见。这里的第一个问题是您需要了解sys\u time sys调用。这里有一个方便的图表,告诉您各种sys调用需要什么作为寄存器中的输入 系统时间是系统调用13,所以
mov eax,13
很好
然而,sys_time还需要在ebx中传递一个内存地址,它在ebx中写入实际时间
一个快速的方法是在堆栈上分配一些空间(我们可以在堆栈上推送任何东西,sys_time值将覆盖它,为什么不将eax的值粘贴到它上)
然后将堆栈指针馈送到ebx
mov ebx, esp
现在进行系统调用
int 80h
现在,我们可以从堆栈中弹出时间(例如,eax)
现在eax包含当前unix时间(即自1970年1月1日起的秒数)
为了避免直接将数字打印到unix控制台的麻烦,我将作弊并提供一个完整的示例,该示例在nasm中编译,并通过gcc与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,您可能必须这样做(并拥有相关的多库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教程的问题,我最近学习了杰夫·邓特曼的“汇编语言分步学习,第三版”。有关详细信息和示例章节,请参阅。不要自责。所有的装配都很糟糕可能值得一提的是您使用的是哪个平台。我使用的是64位Linux,使用的是NASM。@kyl,我想您是在组装32位二进制文件,对吗?因为在64位Linux中,您必须使用64位asm,它看起来与您发布的完全不同。而且,即使它是预期的32位二进制文件,我认为您正在尝试写入(2)一个整数或时间,这取决于您使用的系统调用。不要自责。所有的装配都很糟糕可能值得一提的是您使用的是哪个平台。我使用的是64位Linux,使用的是NASM。@kyl,我想您是在组装32位二进制文件,对吗?因为在64位Linux中,您必须使用64位asm,它看起来与您发布的完全不同。而且,即使它按预期的32位二进制格式工作,我认为您正在尝试写入(2)一个整数或时间,具体取决于您使用的系统调用。sys write在ECX中使用指针,而不是EBX。你想要推…<代码>移动ecx,esp
int 0x80
将推送字节写入标准输出。sys\u write在ECX而不是EBX中使用指针。你想要推…<代码>移动ecx,espint 0x80
将推送字节写入标准输出。