Error A2006: undefined symbol : base_l - Assembler
Формулировка задачи:
Очередная программа не хочет собираться, материться и всё тут... Неопределённый символ, но эти символы объявлены, в чём проблема, что не нравится MASM32?
Код программы:
error A2006: undefined symbol : base_l
error A2006: undefined symbol : base_m
.486P ;разрешение трансляции всех команд Pentium
;Структура для описания дескрипторов сегментов
descr struc ;Начало объявления структуры
lim dw 0 ;границы (биты 0...15)
base_l dw 0 ;база, биты 0...15
base_m db 0 ;база, биты 1...23
attr_1 db 0 ;байт атрибутов 1
attr_2 db 0 ;граница (биты 16...19) и атрибуты 2
base_h db 0 ;база, биты 24...31
descr ends ;конец объявления структуры
data segment use16 ;16 - разрядный сегмент
;Таблица глобальных дескрипторов GDT
gdt_null descr <0,0,0,0,0,0> ;селектор 0, нулевой дескриптор
gdt_data descr <data_size-1,0,0,92h,0,0> ;селектор 8, сегмент данных
gdt_code descr <code_size-1,0,0,98h,0,0> ;селектор 16, сегмент команд
gdt_stack descr <255,0,0,92h,0,0> ;селектор 24, сегмент стека
gdt_screen descr <3999,8000h,0Bh,92h,0,0> ;селектор 32, видеопамять
gdt_size=$-gdt_null ;размер GDT
;Различные данные программы
pdescr df 0 ;псевдодескриптор для команды lgdt
sym db 1 ;символ для вывода на экран
attr db 1Eh ;его атрибут
msg db 27,'[31;42m Вернулись в реальный режим! ',27,'[0m$'
data_size=$-gdt_null ;размер сегмента данных
data ends
text segment use16 ;16 - разрядный сегмент команд
assume cs:text,ds:data
main proc
xor eax,eax ;очистим EAX
mov ax,data ;загрузим в DS сегментный
mov ds,ax ;адрес сегмента данных
;Вычислим 32-битовый линейный адрес сегмента данных и загрузим его
;в дескриптор сегмента данных в таблице глобальных дескрипторов GDT
shl eax,4 ;EAX=линейный базовый адрес
mov ebp,eax ;сохраним его в EBP для будущего
mov bx,offset gdt_data ;BX=смещение дескриптора
mov [bx].base_l,ax ;загрузим младшую часть базы
shr eax,16 ;старшую половину EAX в AX
mov [bx].base_m,al ;загрузим среднюю часть базы
;Вычислим и загрузим в GTD линейный адрес сегмента команд
xor eax,eax ;очистим EAX
mov ax,cs ;сегментный адрес сегмента команд
shl eax,4 ;EAX = линейный базовый адрес
mov bx,offset gdt_code ;BX = смещение дескриптора
mov [bx].base_l,ax ;загрузим младшую часть базы
shr eax,16 ;старшую половину EAX в AX
mov [bx].base_m,al ;загрузим среднюю часть базы
;Вычислим и загрузим в GTD линейный адрес сегмента стека
xor eax,eax ;очистим EAX
mov ax,ss ;сегментный адрес сегмента стека
shl eax,4
mov bx,offset gdt_stack ;
mov [bx].base_l,ax
shr eax,16
mov [bx].base_m,al
;Подготовим псевдодескриптор pdescr и загрузим регистр GDTR
mov dword ptr pdescr+2,ebp ;база GDT
mov word ptr pdescr,gdt_size-1 ;граница GDT
lgdt pdescr ;загрузим регистр GDTR
;Подготовимся к возврату из защищённого режима в реальный
mov ax,40h ;настроим ES на область
mov es,ax ;данных BIOS
mov word ptr es:[67h],offset return ;смещение возврата
mov es:[69h],cs ;сегмент возврата
mov al,0Fh ;выборка байта состояния отключения
out 70h,al ;порт КМОП-микросхемы
mov al,0Ah ;установка режима восстановления
out 71h,al ;в регистре 0Fh сброса процессора
cli ;запрет аппаратных прерываний
;Переход в защищённый режим
mov eax,cr0 ;получим содержимое регистра CR0
or eax,1 ;установим бит защищённого режима
mov cr0,eax ;запишем назад в CR0
;-------------------------------------------------------------------------
;Теперь процессор работает в защищённом режиме
;-------------------------------------------------------------------------
;Загружаем в CS:IP селектор:смещение точки continue
db 0EAh ;код команды FAT JMP
dw offset continue ;смещение
dw 16 ;селектор сегмента команд
continue:
;Делаем адресуемыми данные
mov ax,8 ;селектор сегмента данных
mov ds,ax ;настроим DS на селектор данных?
;Делаем адресуемым стек
mov ax,24 ;селектор сегмента стека
mov ss,ax
;Инициализируем ES
mov ax,32 ;селектор сегмента видеобуфера
mov es,ax ;инициализируем ES
;Выводим на экран тестовую строку символов
mov di,1920 ;начальная позиция на экране
mov cx,80 ;число выводимых символов
mov ax,word ptr sym ;символ+атрибут
scrn:
stosw ;содержимое AX на экран
inc al ;инкремент кода символа
loop scrn ;цикл вывода
;-----------------------------------------------------------------
;Вернёмся в реальный режим
;-----------------------------------------------------------------
mov al,0FEh ;команда сброса процессора
out 64h,al ;в порт 64h
hlt ;Останов процессора до окончания сброса
;---------------------------------------------------------------------
;Теперь процессор снова работает в реальном режиме
;---------------------------------------------------------------------
return:
;Восстановим вычислительную среду реального режима
mov ax,data ;сделаем адресуемыми данные
mov ds,ax
mov ax,stk ;сделаем адресуемым стек
mov ss,ax
mov sp,256 ;настроим SP
sti ;разрешим аппаратные прерывания
;Работаем в DOS
mov ah,09h ;проверим выполнение функции DOS
mov dx,offset msg ;после возврата в реальный режим
int 21h
mov ax,4C00h ;завершим программу обычным образом
int 21h
main endp
code_size=$-main ;размер сегмента команд
text ends
;Сегмент стека
stk segment stack use16 ;16-разрядный сегмент стека
db 256 dup ('^')
stk ends
end mainРешение задачи: «Error A2006: undefined symbol : base_l»
textual
Листинг программы
struc KNIGA {
.prolog dw 0
.ot_avtora dw 0
.glava_1 : dd 0
.glava_2 : db 0
.kartinka dw 0
.epilog dw 0
.soderganie dd 0
};KNIGA
;ends
kng KNIGA ; определение "переменной" типа структура
mov eax,[kng.ot_avtora]
Объяснение кода листинга программы
- Структура KNIGA объявлена с полями: prolog, ot_avtora, glava_1, glava_2, kartinka, epilog, soderganie.
- Переменная kng типа структура KNIGA определена.
- Значение поля ot_avtora структуры KNIGA сохраняется в регистре eax.