Masm error a2006

ASM Community I just started ASM but I have already started to catch on very easily. For the past 3 days I’ve been stuck on the MessageBox/MessageBoxA function. I cannot get a MessageBox no matter how hard I try. When using the code below, I receive this error at assembly, «error a2006: undefined symbol […]

Содержание

  1. ASM Community
  2. Ассемблер MASM не видит функции из «Windows API»-ских библиотек
  3. 1 ответ 1
  4. Error a2006 undefined symbol messagebox
  5. Error a2006 undefined symbol messagebox
  6. Помогите с ассемблером ругается только на call

I just started ASM but I have already started to catch on very easily. For the past 3 days I’ve been stuck on the MessageBox/MessageBoxA function. I cannot get a MessageBox no matter how hard I try. When using the code below, I receive this error at assembly, «error a2006: undefined symbol : MessageBox» & «error a2006: undefined symbol : ExitProcess.» Someone told me it was because the WINAPI.inc include is for 16-bit systems only.

Here’s what I have:

I just looked at the 2 files (WINAPI.inc & WINDOWS.inc) and there are some functions in WINAPI.inc that are required for the program to run that aren’t in WINDOWS.inc but when I try to include both of them I receive this error:

Assembling: C:program.asm.
C:Documents and SettingsAdministratorDesktopSU1.0SourceWINDOWS.inc(73) : error A2111: conflicting parameter definition
C:Documents and SettingsAdministratorDesktopSU1.0SourceWINDOWS.inc(7916) : error A2008: syntax error : offset
C:Documents and SettingsAdministratorDesktopSU1.0Sourceprogram.asm(32) : error A2008: syntax error : in directive
C:Documents and SettingsAdministratorDesktopSU1.0Sourceprogram.asm(99) : error A2006: undefined symbol : MessageBox
C:Documents and SettingsAdministratorDesktopSU1.0Sourceprogram.asm(100) : error A2006: undefined symbol : ExitProcess
C:Documents and SettingsAdministratorDesktopSU1.0Sourceprogram.asm(108) : error A2006: undefined symbol : ExitProcess

I think you have to include either windows.inc or winapi.inc.

The windows.inc file is part of the masm32 package, and only has constants and structures. To declare functions you must use additional include files, also part of the package, one for each dll: user32.inc, kernel32.inc, etc.

I don’t know where does winapi.inc come from, or what it contains, so I can’t help you use it. 🙁

Nevermind I FINALLY figured it out, wow.

Here’s what I did:

Now you can do the same for ExitProcess:

Still I’d recommend you to use hutch’s include files, so you don’t have to do the same for each and every API you want to call. 😯

Источник

Ассемблер MASM не видит функции из «Windows API»-ских библиотек

Изучаю Ассемблер для архитектур x86 Intel-овских процессоров на Windows. Новичок.

Ассемблер MASM не видит функции из «Windows API»-ских библиотек. Вот весь мой код «Hello world»-а через MessageBox. (» .inc «-файлы и прочее использовать не хочу, хочу в деталях самим расписывать и без них делать. Использую не MASM32 из сайта masm32.com, а ml.exe из папки Visual Studio (использую Visual Studio 2019 года. У самого́ Windows 7)).

А консоль выдаёт вот что:

Не понимаю как это решить, чтобы MASM видел что эти функции ( LoadLibraryA , и т.д.) находятся в » kernel32.dll » (на которую в теории должна указывать » kernel32.lib » подключенная с помощью директивы » includelib «)

1 ответ 1

Решил сам. Оказывается просто надо было все функции объявлять с подчёркиванием » _ » в начале имени функции и «собакой» » @ » на конце имени функции после которой указываются количество байт занимаемых параметрами процедуры.

Вот исправленный код объявления их внешними:

И при использовании (например через » call «) тоже надо прописывать их так. Проверял по другому — не работает — писать нужно только так (Windows API-ские функции только, а свои можно хоть как (но надо ли » @ » в своих функциях использовать не знаю)):

А в 64-битной программе эти функции по другому вызываются, без подчёркивания » _ » и без указания собаки » @ » и без указания байт параметров после неё.

Но при передаче в функцию » GetProcAddress » имени функции которую нужно взять из DLL, нужно писать просто имя функции без этих символов.

Только осталась проблема что файл » .exe » сассемблировался не в нужную папку и теперь либо он не сассемблировался, либо его искать надо, но это уже другая тема, не этого вопроса, а сам вопрос решён.
[Решил] Оказывается надо прописать сначала в командной строке путь к папке в которой должен появится файл с помощью » cd «, например » cd «Путь к файлу» «

И, кстати, только что узнал что нужно использовать процедуры с » A » символом на конце, а не » W «, если используешь кавычки ‘ ‘ или » » для вписывания символов в память, иначе будешь получать иероглифы. Но процедуры с » A » символом на конце используются для работы с массивами символов как с 8-битными символами из кодировки ASCII, а процедуры с » W » символом на конце для работы с массивами символов как с 16-битной кодировкой Unicode (которая вроде UTF-16 называется, не помню точно)

Источник

Error a2006 undefined symbol messagebox

Ругается так- D:MYPROGНовая папка(2)Prg_3_1.asm(10) : error A2004: symbol conflict

Подскажите, обьясните причину.

Вот и прога от dorr не компилитя по тем же причинам.

D:MYPROGMass.asm(32) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(35) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(238) : warning A4023: with /coff switch, leading underscore required for start address : start

То- есть, строки
(32)assume ds:@data,es:@data
(35)mov ax, @data

Вот и прога от dorr не компилитя по тем же причинам.

D:MYPROGMass.asm(32) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(35) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(238) : warning A4023: with /coff switch, leading underscore required for start address : start

То- есть, строки
(32)assume ds:@data,es:@data
(35)mov ax, @data

Источник

Error a2006 undefined symbol messagebox

Ругается так- D:MYPROGНовая папка(2)Prg_3_1.asm(10) : error A2004: symbol conflict

Подскажите, обьясните причину.

Вот и прога от dorr не компилитя по тем же причинам.

D:MYPROGMass.asm(32) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(35) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(238) : warning A4023: with /coff switch, leading underscore required for start address : start

То- есть, строки
(32)assume ds:@data,es:@data
(35)mov ax, @data

Вот и прога от dorr не компилитя по тем же причинам.

D:MYPROGMass.asm(32) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(35) : error A2006: undefined symbol : DGROUP
D:MYPROGMass.asm(238) : warning A4023: with /coff switch, leading underscore required for start address : start

То- есть, строки
(32)assume ds:@data,es:@data
(35)mov ax, @data

Источник

Помогите с ассемблером ругается только на call

386
.model flat, stdcall
option casemap :none

include masm32includewindows.inc
include masm32includeuser32.inc
include masm32includekernel32.inc
include masm32includemasm32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.lib
includelib masm32libmasm32.lib

.data
conTitle DB «Sum of integers in array», 0
mes1 DB «Array: «, 0
len_mes1 EQU $-mes1

mes2 DB 0dh, 0ah, «Sum of elements = «, 0
len_mes2 EQU $-mes2

charBuf DB » «, 0
len_charBuf DD $-charBuf
iarray DD -9, 3, -6, 2, 11, -5
larray EQU ($-iarray)/4
ISUM DD 0
lpFmt DB «%d», 0

readBuf DB ?
lenReadBuf DD 1

hStdIn DD 0
hStdOut DD 0

chrsRead DD 0
chrsWritten DD 0

STD_INP_HNDL DD -10
STD_OUTP_HNDL DD -11

.code
start:
call AllocConsole
test EAX, EAX
jz ex
push offset conTitle
call SetConsoleTitleA
test EAX, EAX
jz ex

call GetOut_Hndl
call getInp_hndl

push EBX
mov EBX, offset mes1
mov ECX, len_mes1
call write_con
pop EBX

mov ESI, offset iarray
mov ECX, larray
show_next:
push ESI
push ECX
push DWORD PTR [ESI]
push offset lpFmt
push offset charBuf
call wsprintf
add ESP, 12

push EBX
mov EBX, offset charBuf
mov ECX, len_charBuf
call write_con
pop EBX

call clear_buffer
pop ECX
pop ESI
add ESI, 4
loop show_next

; нахождение суммы элементов массива
mov ECX, larray
mov ESI, offset iarray
finit
fild DWORD PTR [ESI]
next:
fiadd DWORD PTR [ESI+4]
add ESI, 4
loop next
fistp DWORD PTR ISUM
fwait

; преобразование суммы в строку символов

push DWORD PTR ISUM
push offset lpFmt
push offset charBuf
call wsprintf
add ESP, 12

push EBX
mov EBX, offset mes2
mov ECX, len_mes2
call write_con
pop EBX

; вывод значения суммы на экран

push EBX
mov EBX, offset charBuf
mov ECX, len_charBuf
call write_con
pop EBX
call clear_buf

; ожидание ввода с консоли и выход из программы

ошибки только на call
Assembling: C:masm32binwwwwwwww.asm
C:masm32binwwwwwwww.asm(126) : error A2088: END directive required at end of file
C:masm32binwwwwwwww.asm(50) : error A2006: undefined symbol : GET_OUT_HNDL
C:masm32binwwwwwwww.asm(51) : error A2006: undefined symbol : getInp_hndl
C:masm32binwwwwwwww.asm(56) : error A2006: undefined symbol : write_con
C:masm32binwwwwwwww.asm(73) : error A2006: undefined symbol : write_con
C:masm32binwwwwwwww.asm(76) : error A2006: undefined symbol : clear_buf
C:masm32binwwwwwwww.asm(107) : error A2006: undefined symbol : write_con
C:masm32binwwwwwwww.asm(115) : error A2006: undefined symbol : write_con
C:masm32binwwwwwwww.asm(117) : error A2006: undefined symbol : clear_buf

.386
.model flat, stdcall
option casemap :none

include masm32includewindows.inc
include masm32includeuser32.inc
include masm32includekernel32.inc
include masm32includemasm32.inc
includelib masm32libuser32.lib
includelib masm32libkernel32.lib
includelib masm32libmasm32.lib

.data
conTitle DB «Sum of integers in array», 0
mes1 DB «Array: «, 0
len_mes1 EQU $-mes1

mes2 DB 0dh, 0ah, «Sum of elements = «, 0
len_mes2 EQU $-mes2

charBuf DB » «, 0
len_charBuf DD $-charBuf
iarray DD -9, 3, -6, 2, 11, -5
larray EQU ($-iarray)/4
ISUM DD 0
lpFmt DB «%d», 0

readBuf DB ?
lenReadBuf DD 1

hStdIn DD 0
hStdOut DD 0

chrsRead DD 0
chrsWritten DD 0

.code
start:
call AllocConsole
test EAX, EAX
jz ex
push offset conTitle
call SetConsoleTitleA
test EAX, EAX
jz ex

Источник

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
    .586P
;Структура для описания дескрипторов сегментов
descr    struc                               ;
lim     dw  0                                ;граница (биты 0...15)
base_l  dw  0                                ;база, биты 0...15
base_m  db  0                                ;база, биты 16...23
attr_1  db  0                                ;байт атрибутов 1
attr_2  db  0                                ;граница (биты 16...19) и атрибуты 2
base_h  db  0                                ;база, биты 24...31
descr     ends                               ;
;Структура для описания шлюзов ловушек
trap      struc                              ;
offs_l  dw   0                               ;смещение обработчика, биты 0...15
sel     dw   16                              ;селектор сегмента команд
cntr    db   0                               ;не используется
dtype   db   8Fh                             ;тип шлюза - ловушка 80386 и выше
offs_h  dw   0                               ;смещение обработчика, биты 16...31
trap      ends                               ;
 
;Сегмент данных
data   segment use16                         ;16-разрядный сегмент
;Таблица глобальных дескрипторов GDT
gdt_null descr <>                            ;селектор 0
gdt_data descr <data_size-1,,,92h>           ;селектор 8, сегмент данных
gdt_code descr <code_size-1,,,98h>           ;селектор 16, сегмент команд
gdt_stack descr <255,,,92h,,>                ;селектор 24, сегмент стека
gdt_screen descr <3999,8000h,0Bh,92h>        ;селектор 32, видеопамять
gdt_size=$-gdt_null                          ;размер GDT
idt label word                              ;метка начала таблицы дескрипторов исключений
trap <exc0>                                 ;дескриптор исключений 0
trap <dummy>                                ;дескриптор исключений 1
trap <dummy>                                ;дескриптор исключений 2
trap <exc3>                                 ;дескриптор исключений 3
trap <dummy>                                ;дескриптор исключений 4
trap <dummy>                                ;дескриптор исключений 5
trap <dummy>                                ;дескриптор исключений 6
trap <dummy>                                ;дескриптор исключений 7
trap <dummy>                                ;дескриптор исключений 8
trap <dummy>                                ;дескриптор исключений 9
trap <exc10>                                ;дескриптор исключений 10
trap <exc11>                                ;дескриптор исключений 11
trap <exc12>                                ;дескриптор исключений 12
trap <exc13>                                ;дескриптор исключений 13
trap <dummy>                                ;дескриптор исключений 14
trap <dummy>                                ;дескриптор исключений 16
trap <dummy>                                ;дескриптор исключений 17
trap <dummy>                                ;дескриптор исключений 18
idt_size=$-idt                              ;размер таблицы дескрипторов исключений
;Различные данные программы
pdescr    df   0                            ;псевдодескриптор для команд lgdt и lidt
sym       db   1                            ;символ для вывода на экран
attr      db   1Eh                          ;его атрибут
msg       db  27,'[31;42m  Вернулись в реальный режим!  ',27,'[0m$'    
string    db   '**** ****_**** ****_**** ****'
;                0    5    10   15   20   25       позиция в шаблоне
len=$-string
data_size=$-gdt_null                        ;размер сегмента данных
data    ends
 
;Сегмент команд
text   segment use16                        ;16-разрядный сегмент
       assume cs:text,ds:data
       textseg label word                   ;метка начала сегмента команд
exc0   proc                                 ;обработчик исключения 0
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведем адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,0                             ;для вывода на экран номера исключения
      jmp  home                             ;на выход
      
       
exc0   endp
exc3   proc                                 ;обработчик исключения 3
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведен адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,3                             ;для вывода на экран номера исключения
      jmp  home                             ;на выход
exc3   endp
exc10  proc                                 ;обработчик исключения 10
      pop  eax                              ;AX = код ошибки (нам не нужен)
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведем адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,0Ah                           ;для вывода на экран номера исключения
      jmp  home                             ;на выход
exc10  endp
exc11   proc                                ;обработчик исключения 11
      pop  eax                              ;AX = код ошибки (нам не нужен)
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведем адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,0Bh                           ;для вывода на экран номера исключения
      jmp  home                             ;на выход
exc11   endp
exc12   proc                                ;обработчик исключений 12
      pop  eax                              ;AX = код ошибки (нам не нужен)
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведем адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,0Ch                           ;для вывода на экран номера исключения
      jmp  home                             ;на выход
exc12   endp
exc13   proc                                ;обработчик исключения 13
      pop  eax                              ;AX = код ошибки (нам не нужен)
      pop  eax                              ;AX = IP
      mov  si,offset string+5               ;выведем адрес
      call wrd_asc                          ;возврата на экран
      mov  ax,0Dh                           ;для вывода на экран номера исключения
      jmp  home                             ;на выход
exc13   endp
dummy   proc                                ;обработчик остальных исключений   
      mov  ax,5555h                         ;условный код остальных исключений
      jmp  home                             ;на выход
dummy   endp
 
main    proc                                ;основная процедура
      xor  eax,eax                          ;очистим EAX
      mov  ax,data                          ;загрузим в DS сегментный
      mov  ds,ax                            ;адрес сегмента данных
;Вычислим и загрузим в GDT линейный адрес сегмента данных
      shl  eax,4                            ;EAX=линейный базовый адрес
      mov  ebp,eax                          ;сохраним его в EBP для будущего
      mov  bx,offset gdt_data               ;BX = смещение дескриптора
      assume bx:ptr descr
      mov  [bx].base_l,ax                   ;загрузим младшую часть базы
      shr  eax,16                           ;старшую половину EAX в AX
      mov  [bx].base_m,al                   ;загрузим среднюю часть базы
;Вычислим и загрузим в GDT линейный адрес сегмента команд
      xor  eax,4                            ;очистим 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                   ;загрузим среднюю часть базы
;Вычислим и загрузим в GDT линейный адрес сегмента стека
      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
      cli                                    ;запрет аппаратных прерываний
;Загрузим IDTR
      mov  word ptr pdescr,idt_size-1        ;граница
      xor  eax,eax
      mov  ax,offset idt
      add  eax,ebp                           ;линейный адрес IDT
      mov  dword ptr pdescr+2,eax            ;в псевдодескриптор
      lidt pdescr                            ;загрузим IDTR
;Переходим в защищённый режим
      mov  eax,cr0                           ;получим содержимое регистра CR0
      or   eax,1                             ;установим бит защищённого режима
      mov  cr0,eax                           ;запишем назад в CR0
;------------------------------------------------------------------------------;
;Теперь процессор работает в защищённом режиме;
;------------------------------------------------------------------------------;
;Загружаем в CS:IP селектор:смещение точки continue
      db   0EAh                              ;код команды FAR JMP
      dw   offset continue                   ;смещение
      dw   16                                ;селектор сегмента команд
continue:
;Делаем адресуемыми данные
      mov  ax,8                              ;селектор сегмента данных
      mov  ds,ax
;Делаем адресуемым стек
      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  ax,0FFFFh                         ;условный код нормального завершения
home:
      mov  si,offset string                  ;точка перехода из обработчика
      call wrd_asc                           ;преобразуем AX в символьную строку
;Выведем на экран диагностическую строку
      mov  si,offset string
      mov  cx,len
      mov  ah,74h
      mov  di,1280
scrn1:
      lodsb
      stosw
      loop scrn1
;Вернёмся в реальный режим
;Сформируем и загрузим дескрипторы для реального режима
      mov  gdt_data.lim,0FFFFh                  ;граница сегмента данных
      mov  gdt_code.lim,0FFFFh                  ;граница сегмента команд
      mov  gdt_stack.lim,0FFFFh                 ;граница сегмента стека
      mov  gdt_screen.lim,0FFFFh                ;граница доп.сегмента
      push ds                                   ;загрузим теневой регистр
      pop  ds                                   ;сегмента данных
      push ss                                   ;загрузим теневой регистр
      pop  ss                                   ;стека
      push es                                   ;загрузим теневой регистр
      pop  es                                   ;дополнительного сегмента
;Выполним дальний переход для того, чтобы заново загрузить селектор
;в регистр CS и модифицировать его теневой регистр
      db   0EAh                                 ;команда дальнего перехода
      dw   offset go                            ;загрузим теневой регистр
      dw   16                                   ;сегмента команд
;Переключим режим процессора
go:
      mov  eax,cr0                              ;получим содержимое регистра CR0
      and  eax,0FFFFFFFEh                       ;сбросим бит защищённого режима
      mov  cr0,eax                              ;запишем назад в CR0
      db   0EAh                                 ;код команды FAR JMP
      dw   offset return                        ;смещение 
      dw   text                                 ;сегмент
;---------------------------------------------------------------------------;
;Теперь процессор снова работает в реальном режиме                          ;
;---------------------------------------------------------------------------;
return:
;Восстановим вычислительную среду реального режима
      mov  ax,data                              ;сделаем адресуемыми данные
      mov  ds,ax
      mov  ax,stk                               ;сделаем адресуемым стек
      mov  ss,ax
      mov  sp,256                               ;настроим SP
;Восстановим состояние регистра IDTR реального режима
      mov  ax,3FFh                              ;Граница таблицы векторов (1 Кбайт)
      mov  word ptr pdescr,ax
      mov  eax,0                                ;смещение таблицы векторов
      mov  dword ptr pdescr+2,eax
      lidt pdescr                               ;загрузим псевдодескриптор в IDTR
      sti                                       ;разрешим аппаратные прерывания
;Работаем в DOS
      mov  ah,09h                               ;проверим выполнение функций DOS
      mov  dx,offset string                     ;после возврата в реальный режим
      int  21h
      mov  ax,4C00h                             ;завершим программу обычным образом
      int  21h
main   endp
 
;Инструментальные средства - подпрограммы wrd_asc и bin_asc
;преобразование двоичного числа в символьное 16-ричное представление
wrd_asc    proc
       pusha                                ;сохраним все регистры
       mov  bx,0F000h                       ;в BX будет маска битов
       mov  dl,12                           ;в DL будет число сдвигов AX
       mov  cx,4                            ;счётчик цикла
cccc:
       push cx                              ;сохраним его
       push ax                              ;сохраним исходное число в стеке
       and  ax,bx                           ;выделим четвёрку битов
       mov  cl,dl                           ;отправим в CL число сдвигов
       shr  ax,cl                           ;сдвинем на CL бит вправо
       call bin_asc                         ;преобразуем в символ ASCII
       mov  byte ptr [si],al                ;отправим в строку результата
       inc  si                              ;сдвинемся по строке вправо
       pop  ax                              ;вернём в AX исходное число
       shr  bx,4                            ;модифицируем маску битов
       sub  dl,4                            ;модифицируем число сдвигов
       pop  cx                              ;восстановим счётчик цикла
       loop cccc                            ;цикл
       popa                                 ;восстановим все регистры
       ret                                  ;возврат из подпрограммы
wrd_asc   endp
;Подпрограмма преобразования 16-ричной цифры
;Преобразуемая четвёрка битов в младшей половине AL, результат в AL
bin_asc   proc
       cmp  al,9                             ;цифра больше 9?
       ja   lettr                            ;да, преобразование в букву
       add  al,30h                           ;нет преобразуем в символ 0...9
       jmp  ok                               ;и на выход из программы
lettr:
       add  al,37h                           ;преобразуем в символ A...F
ok:
       ret                                   ;возврат в вызывающую процедуру
bin_asc   endp
code_size=$-textseg                          ;размер сегмента команд
text   ends                                  ;конец сегмента команд
 
;Сегмент стека
stk    segment stack use16                   ;16-разрядный сегмент
       db 256 dup ('^')
stk    ends                                  ;конец сегмента стека
 
end   main                                     ;конец программы

KnowledgeBase Archive

An Archive of Early Microsoft KnowledgeBase Articles

View on GitHub


Article: Q59754
Product(s): Microsoft Macro Assembler
Version(s): 5.1,5.1a
Operating System(s): 
Keyword(s): 
Last Modified: 06-MAY-2001

-------------------------------------------------------------------------------
The information in this article applies to:

- Microsoft Macro Assembler (MASM), versions 5.1, 5.1a 
-------------------------------------------------------------------------------

SYMPTOMS
========

Using the "SEG" directive in conjunction with forward reference to a procedure
or a segment name will produce the error

  A2006 : phase error between passes

CAUSE
=====

The assembler incorrectly places a "NOP" instruction in the code generated
during Pass 1. This NOP is not generated in Pass 2, so the assembler generates a
phase error. This phase error will most often happen on the next instruction
that is associated with a fixup.

STATUS
======

Microsoft has confirmed this to be a problem in MASM versions 5.1 and 5.10a.
This problem was fixed in MASM version 6.0.

RESOLUTION
==========

To work around this problem, introduce a NOP that is seen by the assembler only
during the second pass.

MORE INFORMATION
================

The following code produces the errors. The errors do not occur when the ax
register is used. They occur when the bx, cx, and dx registers are used. The
workaround is shown in commented out lines.

Sample Code:
------------

  ;Assemble options needed: none

  ;filler          MACRO                     ;macro that codes a nop
  ;                if2                       ;in the second pass of the
  ;                nop                       ;assembler
  ;                endif
  ;ENDM

  _text           SEGMENT PARA PUBLIC 'CODE'
                  ASSUME CS:_TEXT

                  MOV     cx, SEG proc1     ;error using cx, bx or dx
  ;                filler
                  MOV     ax, SEG proc1     ;no error using ax
                  MOV     cx, SEG stackseg  ;error using cx, bx, or dx
  ;                filler
                  MOV     ax, SEG stackseg  ;no error using ax

  STACKSEG        SEGMENT PARA PUBLIC 'STACK'
                  db 100 dup (?)
  STACKSEG        ENDS

  proc1           PROC    FAR
                  ret
  proc1           ENDP
  _text           ENDS
  END

Additional query words: 5.10 5.10a buglist5.10 buglist5.10a fixlist6.00

======================================================================
Keywords          :  
Technology        : kbMASMsearch kbAudDeveloper kbMASM510 kbMASM510a
Version           : :5.1,5.1a
Solution Type     : kbfix

=============================================================================

THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS
PROVIDED «AS IS» WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS
ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR
ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL,
CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF
MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION
OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES
SO THE FOREGOING LIMITATION MAY NOT APPLY.

Copyright Microsoft Corporation 1986-2002.


  1. dZentle_man

    dZentle_man

    New Member

    Публикаций:

    0

    Регистрация:
    24 авг 2008
    Сообщения:
    414

    Блин, весь извелся, никак не пойму почему компилятор не видит функции. При попытке откомпилить выдает следующее:Исходный текст:


  2. twgt

    twgt

    New Member

    Публикаций:

    0

    Регистрация:
    15 янв 2007
    Сообщения:
    1.494

    http://www.wasm.ru/article.php?article=1001002
    Обратить внимание на include!


  3. dZentle_man

    dZentle_man

    New Member

    Публикаций:

    0

    Регистрация:
    24 авг 2008
    Сообщения:
    414

    А че на него обращать то? Все буква в букву, как и там. Статью читал уже. Либо в упор не вижу (тогда может напишешь в чем конкретно косяк?), либо дело не в этом.


  4. agrischuk

    agrischuk

    New Member

    Публикаций:

    0

    Регистрация:
    12 янв 2009
    Сообщения:
    47

    Подсказка:
    extrn __imp__ExitProcess@4 : dword
    ExitProcess equ __imp__ExitProcess@4

    В книжке, если читать внимательнее приведены inc файлы. Возможно в новом издании еще больше ошибок наделали.


  5. mupsy

    mupsy

    New Member

    Публикаций:

    0

    Регистрация:
    26 ноя 2008
    Сообщения:
    55

    dZentle_man
    include /masm32/include/kernel32.inc
    include /masm32/include/user32.inc
    include /masm32/include/shell32.inc
    includelib masm32libshell32.lib
    includelib masm32libkernel32.lib
    includelib masm32libuser32.inc
    вот так напиши в начале…


  6. dZentle_man

    dZentle_man

    New Member

    Публикаций:

    0

    Регистрация:
    24 авг 2008
    Сообщения:
    414

    agrischuk, спасибо, помогло. Насчет .inc знаю, но мой компилятор выдает на них сотню ошибок «A2119: language type must be specified», поэтому я решил в этом случае задать все вручную, чтобы хотя бы понять как оно работает. В книжках че попало пишут. Во времена Зубкова еще даже 98-й винды не существовало в природе, поэтому мой компилятор может не поддерживать его пример. У Iczelion’а все завязано на invoke, но invoke особого понимания как все происходит на самом деле не дает — случись ошибка и я не буду знать где ее искать. Собственно на invoke я тоже пробовал завязать, но так ничего и не вышло.

    В общем сейчас компилятор функции видит, так что по теме мне помогли. Всем спасибо за внимание


  7. Mikl___

    Mikl___

    Супермодератор
    Команда форума

    Публикаций:

    14

    Регистрация:
    25 июн 2008
    Сообщения:
    3.468

    dZentle_man посмотри здесь
    можно сразу писать без «ExitProcess equ __imp__ExitProcess@4»
    push ebx
    call _imp__ExitProcess@4
    тогда достаточно «includelib masm32libkernel32.lib» а строка «include masm32includekernel32.inc» не нужна — это для вызова invoke


  8. dZentle_man

    dZentle_man

    New Member

    Публикаций:

    0

    Регистрация:
    24 авг 2008
    Сообщения:
    414

    Ну я в общем то выбрал средний вариант — в сегменте данных определил импорт функции через equ, в обход .inc файлов. Способ вполне прозрачный и удобнее, чем писать полное имя функции в сегменте кода. За ссылку спасибо, раскурю на досуге.


WASM

Очередная программа не хочет собираться, материться и всё тут…

error A2006: undefined symbol : base_l
error A2006: undefined symbol : base_m

Неопределённый символ, но эти символы объявлены, в чём проблема, что не нравится MASM32?

Код программы:

   .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

Понравилась статья? Поделить с друзьями:
  • Marymorals d20 коды ошибок
  • Marvell 91xx sata 6g controller ошибка код 10
  • Marvel ultimate alliance 2 ошибка 0xc0000142 как исправить
  • Marvel ultimate alliance 2 ошибка 0xc0000142 windows 10
  • Martin garrix jay hardway error 404 скачать