NASM распечатывает время - код ничего не выводит - PullRequest
1 голос
/ 07 августа 2009

Я только начинаю работать с 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

Ответы [ 2 ]

6 голосов
/ 09 июля 2011

Первая проблема заключается в том, что вам нужно понять вызов 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 (то есть количество секунд с 01 января 1970 года.)

Чтобы избежать сложности печати чисел непосредственно на консоли Unix, я приведу чит и приведу полный пример, который компилируется в nasm и связывается с библиотекой c через gcc и использует 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 и сумел скомпилировать вышеуказанный код. Дайте мне знать, если у вас возникнут проблемы.

Чтобы ответить на ваш вопрос, касающийся учебных пособий по назму, я недавно выучил у Джеффа Дунтманна «Сборочный язык шаг за шагом, третье издание». См. http://www.duntemann.com/assembly.html для деталей и примеров глав.

3 голосов
/ 07 августа 2009

Это ваш пример, переведенный на 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);
}
...