LINUX.ORG.RU

Компоновщик ассемблера ругается

 ,


0

1

Доброго вечера!

Потихоньку решаю ассемблерную часть из задачника А.В. Столярова. По итогу решения задачки 3.20 «Получи на вводе два числа. Выведи их сумму, разность и произведение» родил данный код:

%include"stud_io.inc"
global  _start

section .bss
FstArg  resd 1
SndArg  resd 1
string  resb 10
summ    resd 10
diff    resd 10
prod    resd 20

section .data
ErrMsg  db "There must be two numbers divided with one space symbol"
factor  db 10
divider dw 10

section .text
_start  xor     eax, eax; prepare char buffer
        xor     ebx, ebx; prepare current number holder (arg calculation)
        xor     ecx, ecx; prepare number counter
        xor     edx, edx; prepare data register
        mov     dword [FstArg], 0
                        ; prepare 1st argument
        mov     dword [SndArg], 0
                        ; prepare 2nd argument
NRead:  GETCHAR         ; read a char
        cmp     eax, ' '; do we have space character? 
        je      ZChck   ; then check - has anything already been printed?       
        jmp     NxtStg  ; if we dont have space char - continue alalyz char
ZChck:  cmp     ecx, 0  ; has anything already been printed?
        je      ErrPrt  ; if not then print error message
        jmp     ArgPr1  ; prepare 1st argument
NxtStg: cmp     eax, '0'; if we have ascii symbol less than '0' 
        jb      ErrPrt  ; then print error message
        cmp     eax, '9'; if we have ascii symbol more than '9'
        ja      ErrPrt  ; then print error message 
        sub     eax, '0'; convert ascii code into a number
        inc     ecx     ; increase number counter       
        mov     [string + ecx - 1], al
                        ; write another number into array
        jmp     NRead   ;
ArgPr1  xor     eax, eax; prepare the accamulator
lp:     mov     ebx, [string + ecx - 1]
                        ; get the current number from the array
        mul     byte [factor]
                        ; multiplying accumulator value by 10
        add     eax, ebx; adding to accumulator current number
        loop    lp
        add     dword [FstArg], eax
                        ; we got complete 1st argument now
        mov     ecx, 10 ; prepare counter for string cleanup 
StrClUp:mov     byte [string + ecx - 1], 0
                        ; set current byte to zero
        loop    StrClUp
        xor     eax, eax; prepare char buffer
        xor     ebx, ebx; prepare current number holder (arg calculation)
        xor     ecx, ecx; prepare the counter
NRead2  :GETCHAR        ; read a char
        cmp     eax, 10 ; do we have break line character? 
        je      ZChck2  ; then check - has anything already been printed?       
        jmp     NxtStg2 ; if we dont have space char - continue alalyz char
ZChck2: cmp     ecx, 0   ; has anything already been printed?
        je      ErrPrt  ; if not then print error message
        jmp     ArgPr2  ; prepare 2nd argument
NxtStg2:cmp     eax, '0'; if we have ascii symbol less than '0' 
        jb      ErrPrt  ; then print error message
        cmp     eax, '9'; if we have ascii symbol more than '9'
        ja      ErrPrt  ; then print error message 
        sub     eax, '0'; convert ascii code into a number
        inc     ecx     ; increase number counter       
        mov     [string + ecx - 1], al
                        ; write another number into array
        jmp     NRead2  ;
ErrPrt: PRINT   ErrMsg
ArgPr2: xor     eax, eax; prepare the accamulator
lp2:    mov     ebx, [string + ecx - 1]
                        ; get the current number from the array
        mul     byte [factor]
                        ; multiplying accumulator value by 10
        add     eax, ebx; adding to accumulator current number
        loop    lp2
        add     dword [SndArg], eax
                        ; we got complete 2nd argument now
        PRINT   "SUM"   ; <<<< sum opperation
        PUTCHAR 10
        add     eax, [FstArg]
lp3:    cmp     eax, 0  ; have we finished?
        je      SumPrt
        div     dword [divider]
        inc     ecx
        mov     [summ + ecx - 1], edx
        jmp     lp3
SumPrt: xor     ebx, ebx; PRINT SUM     
lp4:    mov     ebx, [string + ecx - 1]
                        ; copying a number from string array
        add     ebx,'0' ; converting a number from binary to ascii format
        PUTCHAR bl      ; print numbers of the string array
        loop    lp4     ; one by one
        PUTCHAR 10
        xor     eax, eax
        xor     ebx, ebx
        xor     ecx, ecx
        xor     edx, edx
        PRINT   "DIFF"  ; <<<< sub operation
        PUTCHAR 10
        mov     eax, [FstArg]
        mov     ebx, [SndArg]
        sub     eax, ebx; do we have negative difference?
        jns     lp4     ; if not - proceed with the standart algoritm
        not     eax     ; else take additional actions - invert
        add     eax, 1  ; and add 1 - so we convert neg num into positiv one
        PUTCHAR "-"
lp5:    cmp     eax, 0  ; (have we finished?) if no start work with pos num
        je      SubPrt
        div     dword [divider]
        inc     ecx
        mov     [diff + ecx - 1], edx
        jmp     lp5
SubPrt: xor     ebx, ebx; PRINT SUB
lp6:    mov     ebx, [diff + ecx - 1]
                        ; copying a number from string array
        add     ebx, '0'; converting a number from binary to ascii format
        PUTCHAR bl      ; print numbers of the string array
        loop    lp6     ; one by one
        PUTCHAR 10
        xor     eax, eax
        xor     ebx, ebx
        xor     ecx, ecx
        xor     edx, edx
        PRINT   "PROD"  ; <<<< mul operation
        PUTCHAR 10
        mov     eax, [FstArg]
        mov     ebx, [SndArg]
        mul     ebx
        mov     ecx, 20 
lp7:    cmp     eax, 0  ; (have we finished?) if no start work with pos num
        je      MulPrt
        div     dword [divider]
        dec     ecx
        mov     [prod + ecx], edx
        jmp     lp7
        cmp     edx, 0  ; does the second multiplyer register is empty?
        je      MulPrt  ; then just print the number
        mov     eax, edx; else start ro work with it too
lp8:    cmp     eax, 0  ; (have we finished?) if no start work with pos num
        je      MulPrt
        div     dword [divider]
        dec     ecx
        mov     [prod + ecx], edx
        jmp     lp8
MulPrt: nop
lp9:    mov     ebx, [prod + ecx]
                        ; copying a number from string array
        inc     ecx
        add     ebx, '0'; converting a number from binary to ascii format
        PUTCHAR bl      ; print numbers of the string array
        loop    lp9     ; one by one
        PUTCHAR 10

При запуске компоновщика получаю данный поток нецензурной брани в свой адрес:

~/assembly$ ld -m elf_i386 TwoNumSumDifMul.o -o TwoNumSumDifMul
TwoNumSumDifMul.o: в функции «..@10.str»:
TwoNumSumDifMul.asm:(.text+0xfc): перемещение обрезано по месту: R_386_8 у неопределённого символа «.data»

Перемещено hobbit из general

При запуске компоновщика получаю данный поток нецензурной брани в свой адрес

Тут нет ничего нецензурного (но желательно отрудить локализацию, чтобы получать ошибки на английском). Главное здесь - это .text+0xfc - указание на место в коде, где произошла ошибка.

Запускаем objdump -d TwoNumSumDifMul.o и видим, что по адресу 0xfc находится инструкция add %dl,0x51(%edx). Методом пристального взгляда определяем, что эта инструкция появляется из макроса PRINT ErrMsg (т.к. находится между sub eax, 0x30; inc ecx; mov; jmp и xor eax, eax).

На этом мое асм-фу все.

annulen ★★★★★
()
Последнее исправление: annulen (всего исправлений: 1)