Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 26.06.2022, 12:49   #1
ИваннавИ
Пользователь
 
Регистрация: 13.10.2020
Сообщений: 22
По умолчанию Ассемблер

Всем привет. В общем возникла проблема при компиляции ассемблера (задание по учебе) возникает ошибка (Illegel instruction) в первой строке. Я ничего не понимаю. подскажите пожалуйста, как скомпилировать следующий код (использую FASM).
П.С. Мне нужно будет использовать потом эту функцию в Си. (Такое задание)
Код:
long_division PROC public

        ; пролог
        push    rbp
        mov     rbp, rsp
      
        mov     eax, 10000 ; выделяем место на стеке под делимое
        sub     rsp, rax

        xor     r9, r9 ; временная переменная (temp) = 0
        mov     r11, r8 ; r11 = длина делимого (strlen(dividend))
        mov     rbx, rdx ; rbx = делитель (divisor)
        mov     rdi, rcx ; rdi = адрес делимого (строки делимого)
        test    r8, r8 ; проверяем, равна ли длина делимого нулю
        jle     short exit ; если да - выходим
        mov     r8, r9 ; r8 = i = 0
        mov     r10, r9 ; r10 = временная переменная = 0
div_algo:
        ; temp = (temp * 2 + (dividend[i] - 48))

        movsx   eax, BYTE PTR [r8+rdi] ; eax = dividend[i]
        lea     rcx, QWORD PTR [rsp] ; rcx = адрес стека
        sub     eax, 48 ; вычитаем 48 из dividend[i] (перевод символа в число)
        add     rcx, r10 ; сдвигаем
        cdqe    ; dword -> qword
        inc     r10 ; r10++
        lea     r9, QWORD PTR [rax+r9*2] ; r9 = rax + r9 * 2 

        ; if (temp < divisor) jmp lower else jmp greater

        cmp     r9, rbx ; сравниваем получившееся значение с делителем 
        jae     short greater ; если больше(divisor), то переходим
        mov     al, 48 ; al = 48
        jmp     short lower ; переходим на lower

greater:
        ; answer[i] = (temp / divisor) + 48
        ; temp = temp % divisor;

        xor     rdx, rdx ; rdx = 0
        mov     rax, r9 ; rax = r9
        div     rbx ; rax = rax / rbx, rdx = остаток от деления
        mov     r9, rdx ; r9 = rdx = остаток от деления
        add     al, 48  ; al += 48  

lower:
        ; answer[i] = 48 (символ '0')

        inc     r8 ; i++
        mov     BYTE PTR [rcx], al ; записываем на стек al
        cmp     r8, r11 ; сравниваем i и длину делемого
        jl      short div_algo ; если меньше, то повторяем алгоритм

exit:
        lea     rax, QWORD PTR [rsp] ; rax = адрес стека (там хранится ответ)
        add     rsp, 10000 ; восстанавливаем стек

        ; эпилог
                          pop     rbp
        ret

long_division ENDP

end

Последний раз редактировалось ИваннавИ; 26.06.2022 в 12:52.
ИваннавИ вне форума Ответить с цитированием
Старый 26.06.2022, 13:14   #2
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Эта функция написана не на fasm. Скорее всего надо использовать masm.
Если в результате получите .obj файл, тогда его можно будет включить в проект на c/c++ и использовать данную функцию.
macomics вне форума Ответить с цитированием
Старый 26.06.2022, 13:43   #3
ИваннавИ
Пользователь
 
Регистрация: 13.10.2020
Сообщений: 22
По умолчанию

macomics,
вот что получается
C:\Projects>ml /c /coff Control.asm
Microsoft (R) Macro Assembler Version 6.14.8444
Copyright (C) Microsoft Corp 1981-1997. All rights reserved.

Assembling: Control.asm
Control.asm(1) : error A2034: must be in segment block : long_division
Control.asm(4) : error A2034: must be in segment block
Control.asm(5) : error A2034: must be in segment block
Control.asm(7) : error A2085: instruction or register not accepted in current CPU mode
Control.asm(8) : error A2034: must be in segment block
Control.asm(10) : error A2034: must be in segment block
Control.asm(11) : error A2034: must be in segment block
Control.asm(12) : error A2034: must be in segment block
Control.asm(13) : error A2034: must be in segment block
Control.asm(14) : error A2034: must be in segment block
Control.asm(15) : error A2034: must be in segment block
Control.asm(16) : error A2034: must be in segment block
Control.asm(17) : error A2034: must be in segment block
Control.asm(18) : error A2034: must be in segment block
Control.asm(21) : error A2085: instruction or register not accepted in current CPU mode
Control.asm(22) : error A2034: must be in segment block
Control.asm(23) : error A2085: instruction or register not accepted in current CPU mode
Control.asm(24) : error A2034: must be in segment block
Control.asm(25) : error A2008: syntax error : cdqe
Control.asm(26) : error A2034: must be in segment block
Control.asm(27) : error A2034: must be in segment block
Control.asm(31) : error A2034: must be in segment block
Control.asm(32) : error A2034: must be in segment block
Control.asm(33) : error A2034: must be in segment block
Control.asm(34) : error A2034: must be in segment block
Control.asm(36) : error A2034: must be in segment block
Control.asm(40) : error A2034: must be in segment block
Control.asm(41) : error A2034: must be in segment block
Control.asm(42) : error A2034: must be in segment block
Control.asm(43) : error A2034: must be in segment block
Control.asm(44) : error A2034: must be in segment block
Control.asm(46) : error A2034: must be in segment block
Control.asm(49) : error A2034: must be in segment block
Control.asm(50) : error A2034: must be in segment block
Control.asm(51) : error A2034: must be in segment block
Control.asm(52) : error A2034: must be in segment block
Control.asm(54) : error A2034: must be in segment block
Control.asm(55) : error A2034: must be in segment block
Control.asm(56) : error A2034: must be in segment block
Control.asm(59) : error A2034: must be in segment block
Control.asm(60) : error A2034: must be in segment block
Control.asm(62) : fatal error A1010: unmatched block nesting : long_division

C:\Projects>
ИваннавИ вне форума Ответить с цитированием
Старый 26.06.2022, 14:04   #4
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Правильно. Это только одна функция. Заголовок файла отсутствует. Но синтаксис директив не похож на тот что использует fasm
Код:
long_division PROC public
; fasm
; proc long_division, public
, да и в командах используется синтаксис masm
Код:
lea     r9, QWORD PTR [rax+r9*2]
; fasm
; lea r9, qword [rax+r9*2]
; ptr - лишнее, но в masm оно требуется
. Даже если и так. Для fasm заголовок тоже отсутствует.

Порядок ключей masm важен. Попробуйте собирать так
Код:
ml64 /c Control.asm

Последний раз редактировалось macomics; 26.06.2022 в 14:07.
macomics вне форума Ответить с цитированием
Старый 26.06.2022, 14:20   #5
ИваннавИ
Пользователь
 
Регистрация: 13.10.2020
Сообщений: 22
По умолчанию

macomics, Простите, не сочтите за наглость, но не поможите ли вы мне составить заголовок для этого файла?
ИваннавИ вне форума Ответить с цитированием
Старый 26.06.2022, 14:28   #6
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Проблема в том, что эта функция сама по себе написана безобразно.
Код:
exit:
        lea     rax, QWORD PTR [rsp] ; rax = адрес стека (там хранится ответ)
        add     rsp, 10000 ; восстанавливаем стек
; mov rax, rsp
; но не в этом проблема. Возвращается адрес в стеке, который может быть затерт при дальнейшей работе алгоритма.
Еще и используются регистры процессора, значения в которых необходимо восстанавливать перед возвратом из функции.
Код:
rax = rsp - 10000: 0x0000000000000000; начало буфера
...
      rsp - 00024: 0x0000000000000000 ; конец буфера
      rsp - 00016: rbp
      rsp - 00008: rip
rsp = rsp + 00000: 0x0000000000000000
; после вызова printf("%s", long_division("11111111", 111, 8))
rax = rsp - 10000: Возможно затерто
...
      rsp - 00024: Точно затерто
      rsp - 00016: rbp
      rsp - 00008: rip
rsp = rsp + 00000: 0x0000000000000000
Как-то так. Проще переписать.

Так же не понятно вот это
Код:
lea     r9, QWORD PTR [rax+r9*2]
Судя по этой команде на вход этой функции поступает строка с числом в двоичной системе счисления. Но тогда лучше выполнять деление не побитовое, а переводить число группами по 32 или 64 бита.

Последний раз редактировалось macomics; 26.06.2022 в 14:47.
macomics вне форума Ответить с цитированием
Старый 26.06.2022, 15:23   #7
ИваннавИ
Пользователь
 
Регистрация: 13.10.2020
Сообщений: 22
По умолчанию

Цитата:
Сообщение от macomics Посмотреть сообщение
Проблема в том, что эта функция сама по себе написана безобразно.
Код:
exit:
        lea     rax, QWORD PTR [rsp] ; rax = адрес стека (там хранится ответ)
        add     rsp, 10000 ; восстанавливаем стек
; mov rax, rsp
; но не в этом проблема. Возвращается адрес в стеке, который может быть затерт при дальнейшей работе алгоритма.
Еще и используются регистры процессора, значения в которых необходимо восстанавливать перед возвратом из функции.
Код:
rax = rsp - 10000: 0x0000000000000000; начало буфера
...
      rsp - 00024: 0x0000000000000000 ; конец буфера
      rsp - 00016: rbp
      rsp - 00008: rip
rsp = rsp + 00000: 0x0000000000000000
; после вызова printf("%s", long_division("11111111", 111, 8))
rax = rsp - 10000: Возможно затерто
...
      rsp - 00024: Точно затерто
      rsp - 00016: rbp
      rsp - 00008: rip
rsp = rsp + 00000: 0x0000000000000000
Как-то так. Проще переписать.

Так же не понятно вот это
Код:
lea     r9, QWORD PTR [rax+r9*2]
Судя по этой команде на вход этой функции поступает строка с числом в двоичной системе счисления. Но тогда лучше выполнять деление не побитовое, а переводить число группами по 32 или 64 бита.
macomics,
macomics, не понимаю. вместо чего переписать?
ИваннавИ вне форума Ответить с цитированием
Старый 26.06.2022, 15:39   #8
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Все проще переписать.
  • Вместо побитового деления в столбик использовать нормальный алгоритм деления длинных чисел (128-бит / 64-бит или 64-бит/32-бит, иначе какой смысл писать это на ассемблере).
  • Использовать внешний буфер для результата, а не выделять его в стеке (мало того, что его не корректно выделяют, так еще и результат в нем будет затерт при дальнейшем исполнении алгоритма).
  • Регистры процессора rbx, rbp, rsi, rdi (а некоторые компиляторы c++ требуют еще и r11, r12, r13, r14, r15) необходимо восстанавливать перед возвратом из функции.
Доводить эту функцию до условно рабочего состояния не имеет смысла. В ней уже содержатся явные ошибки, которые выскочат во время ее использовании (даже если она будет откомпилирована).

Последний раз редактировалось macomics; 26.06.2022 в 15:45.
macomics вне форума Ответить с цитированием
Старый 26.06.2022, 15:43   #9
ИваннавИ
Пользователь
 
Регистрация: 13.10.2020
Сообщений: 22
По умолчанию

macomics,
Спасибо Вам
ИваннавИ вне форума Ответить с цитированием
Старый 26.06.2022, 15:55   #10
macomics
Участник клуба
 
Регистрация: 17.04.2022
Сообщений: 1,833
По умолчанию

Код:
cdqe    ; dword -> qword ; edx:eax знаковое расширение eax
; cdq ; rax знаковое расширение eax
; cqo ; rdx:rax знаковое расширение rax
; чтобы можно было написать idiv rbx
div rbx
; деление знаковых чисел командой деления без знаковых чисел даст ошибку integer overflow
Деление выполнено не верно.

Последний раз редактировалось macomics; 26.06.2022 в 16:05.
macomics вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ассемблер SWEET_15 Помощь студентам 3 06.09.2016 08:45
Ассемблер Glitcher Помощь студентам 3 17.04.2014 21:01
ассемблер kazhimukan Общие вопросы Delphi 2 07.05.2013 21:50
Ассемблер vibraxo Помощь студентам 2 05.05.2013 20:37
Ассемблер Feelnoobskill Фриланс 1 16.04.2013 12:22