LINUX.ORG.RU

Ошибки в хэлловорлде на ассемблере NASM

 , ,


0

1

Добрый день!

Прохожу материал из книжки А.В. Столярова «Программирование. Введение в профессию». Начал часть, посвящённую ассемблеру. Прочитал «3.2. Основы системы комманд i386». Решил на память написать программу, которая пять раз печатает «Hello». Получилось следующее:

%include "stud_io.inc"
global   _start

section .text
_start: mov     eax, 5
rep:    cmp     eax, 0
        je      quit
        PRINT   "Hello"
        PUTCHAR 10
        dec     eax
        jmp     rep
quit:   FINISH

После команды оттранслировать файл с текстом программы в объектный файл

nasm -f elf hello5rep.asm

получил следующие ошибки:

hello5rep.asm:6: error: parser: instruction expected
hello5rep.asm:11: error: expression syntax error

У автора программа выглядит следующим образом:

%include "stud_io.inc"
global  _start

section .text
_start: mov     eax, 0
repeat: PRINT   "Hello"
        PUTCHAR 10
        inc     eax
        cmp     eax, 5
        jl      repeat
        FINISH

Конечно, по памяти переписал я её менее изящно, но причины возникающих ошибок всё равно не пойму.

ЧЯДНТ?

Ответ на: комментарий от rootree
;; File stud_io.inc for both Linux and FreeBSD.
;;
;; Copyright (c) Andrey Vikt. Stolyarov, 2009, 2015, 2017, 2021
;;
;; I, the author, hereby grant everyone the right to use this file for any
;; purpose, in any manner, in it's original or modified form, provided that
;; modified versions are clearly marked as such AND the original author's
;; copyright notice is kept along with the other authors' copyright notices
;; as appropriate within the file.
;;
;; Only the file as such must retain the copyright notice.  Programs created
;; using this file (e.g. binaries) don't need to have any mentions of the fact
;; this file was used to create them.
;;
;; This file is provided as is, with absolutely NO WARRANTY, and this
;; statement must be taken literally: "NO" means "NO", period.  Please be
;; sure to search Internet for various types of warranty (e.g., implied,
;; hidden, etc) and take into account that you don't have them all.
;;

%define STUD_IO_LINUX
;%define STUD_IO_FREEBSD

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; system dependend part

%ifdef STUD_IO_LINUX

; generic 3-param syscall
%macro _syscall_3 4
        push edx
        push ecx
        push ebx ; it is senseless to save eax as it holds the return
        push %1
        push %2
        push %3
        push %4
        pop edx
        pop ecx
        pop ebx
        pop eax
        int 0x80
        pop ebx
        pop ecx
        pop edx
%endmacro

; syscall_exit is the only syscall we use that has 1 parameter
%macro _syscall_exit 1
        mov ebx, %1     ; exit code
        mov eax, 1      ; 1 = sys_exit
        int 0x80
%endmacro

%elifdef STUD_IO_FREEBSD

; generic 3-param syscall
%macro _syscall_3 4
        push    %4
        push    %3
        push    %2
        mov     eax, %1
        push    eax
        int     0x80
        add     esp, 16
%endmacro

%macro _syscall_exit 1
        push    %1      ; exit code
        mov     eax, 1  ; 1 = sys_exit
        push    eax
        int     0x80
        ; no cleanup - this will never return anyway
%endmacro

%else
%error You must define either STUD_IO_LINUX or STUD_IO_FREEBSD
%endif

;; system dependent part ends here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

; %1: descriptor   %2: buffer addr   %3: buffer length
; output: eax: read bytes
%macro _syscall_read 3
        _syscall_3 3,%1,%2,%3
%endmacro

; %1: descriptor   %2: buffer addr   %3: buffer length
; output: eax: written bytes
%macro _syscall_write 3
        _syscall_3 4,%1,%2,%3
%endmacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%macro  PRINT 1
        pusha
        pushf
        jmp %%astr
%%str   db      %1
%%strln equ     $-%%str
%%astr: _syscall_write 1, %%str, %%strln
        popf
        popa
%endmacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%macro  PUTCHAR 1
        pusha
        pushf
%ifstr %1
        mov     al, %1
%elifnum %1
        mov     al, %1
%elifidni %1,al
        nop
%elifidni %1,ah
        mov     al, ah
%elifidni %1,bl
        mov     al, bl
%elifidni %1,bh
        mov     al, bh
%elifidni %1,cl
        mov     al, cl
%elifidni %1,ch
        mov     al, ch
%elifidni %1,dl
        mov     al, dl
%elifidni %1,dh
        mov     al, dh
%else
        mov     al, %1  ; let's hope it is a memory location such as [var]
%endif
        sub     esp, 4  ; reserve memory for buffer
        mov     edi, esp
        mov     [edi], al
        _syscall_write 1, edi, 1
        add     esp, 4
        popf
        popa
%endmacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%macro  GETCHAR 0
        pushf
        push    edi
        sub     esp, 4
        mov     edi, esp
        _syscall_read 0, edi, 1
        cmp     eax, 1
        jne     %%eof_reached
        xor     eax, eax
        mov     al, [edi]
        jmp     %%gcquit
%%eof_reached:
        xor     eax, eax
        not     eax             ; eax := -1
%%gcquit:
        add     esp, 4
        pop     edi
        popf
%endmacro

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
%macro FINISH 0-1 0
        _syscall_exit %1
%endmacro
KOMMUNIST90 ()

rep - это мнемоника инструкции x86, ее нельзя использовать в качестве имени метки

Кстати, yasm выдает немного более информативные диагностики, чем nasm:

$ yasm -f elf hello5rep.asm
hello5rep.asm:6: error: junk at end of line, first unrecognized character is `:'
hello5rep.asm:11: error: undefined symbol `rep' (first use)
hello5rep.asm:11: error:  (Each undefined symbol is reported only once.)
annulen ★★★★★ ()
Последнее исправление: annulen (всего исправлений: 1)

ЧЯДНТ?

1.rep - в резерве, repeat - нет 2.код 32bit

kindof ()
Ответ на: комментарий от annulen

rep - это мнемоника инструкции x86, ее нельзя использовать в качестве имени метки

сорян, не заметил )

kindof ()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.