Материал: 1328

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

ret LongShiftRight2 endp

Ассемблер обеспечивает, что инструкция ret будет ближнего типа, так как LongShiftRight2 это процедура ближнего типа (near). Однако, если директиву proc изменить следующим образом:

LongShiftRight2 proc far,

то будет генерироваться инструкция ret дальнего типа (far).

Часто группируют в одной и той же процедуре несколько процедур. Поскольку в этих процедурах отсутствует соответствующая директива proc, их инструкции ret будут иметь тип той процедуры, в которую они заключены, а для конкретных подпрограмм этот тип не всегда может оказаться корректным.

Например:

; Подпрограмма дальнего типа для сдвига dx:ax на 2 бита

LongShiftRight2 proc far

 

call

LongShiftRight

; сдвиг dx:ax вправо на 1 бит

call

LongShiftRight

; сдвиг dx:ax вправо еще на 1 бит

ret

 

 

 

LongShiftRight:

 

 

shr

dx,1

 

 

rcr

ax,1

; сдвиг dx:ax вправо на 1 бит

ret

 

 

 

LongShiftRight2 endp

работает неправильно. Процедура LongShiftRight2 обращается с вызовом ближнего типа к LongShiftRight (так как они находятся в одном сегменте кода). Однако, так как LongShiftRight встроена в процедуру LongShiftRight2, то возврат в конце подпрограммы LongShiftRight становится возвратом дальнего типа, а когда вызову ближнего типа соответствует возврат дальнего типа, это с большой вероятностью может привести к сбою (аварийному завершению программы).

Хорошим решением здесь будет наличие в каждой подпрограмме директивы proc. Вложенные директивы proc прекрасно работают.

; Подпрограмма дальнего типа для сдвига dx:ax на 2 бита.

;

LongShiftRight2

proc far

 

call

LongShiftRight

; сдвиг dx:ax вправо на 1 бит

call

LongShiftRight

; сдвиг dx:ax вправо еще на 1 бит

ret

 

 

 

LongShiftRight

proc near

 

shr

dx,1

 

56

 

 

 

rcr ax,1

; сдвиг dx:ax вправо на 1 бит

ret

 

LongShiftRight2

endp

LongShiftRight

endp

Также, как и последующие процедуры:

; Подпрограмма дальнего типа для сдвига dx:ax на 2 бита.

;

LongShiftRight2

proc far

call

LongShiftRight; сдвиг dx:ax вправо на 1 бит

call

LongShiftRight; сдвиг dx:ax вправо еще на 1 бит

ret

 

 

LongShiftRight2

endp

LongShiftRight

proc near

shr

dx,1

 

rcr

ax,1 ; сдвиг dx:ax вправо на 1 бит

ret

 

 

LongShiftRight

endp

Для явной генерации ближнего или дальнего возврата можно использовать соответственно инструкции retn и retf. Вы можете обеспечить с их помощью корректную генерацию инструкций возврата.

7.21. Ошибки при использовании условных переходов

Использование в языке ассемблера инструкций условных переходов (je, jne, jc, jnc, ja, jb, jg и т.д.) обеспечивает большую гибкость в программировании, но при этом очень просто ошибиться, выбрав неверный переход. Типичные ошибки:

7.21.1.Использование инструкций ja, jb, jae или jbe для сравнения значений со знаком или, соответственно, инструкций jg, jl, jge или jle для сравнения беззнаковых значений.

7.21.2.Использование, скажем, инструкции ja там, где нужно использовать jae. Нужно помнить о том, что без буквы e в конце инструкции в сравнении не учитывается случай, когда два операнда равны.

7.21.3.Использование инвертированной логики, например, применение инструкции js там, где нужно использовать jns.

Один из подходов, позволяющий минимизировать ошибки при использовании условных переходов состоит в комментировании

57

переходов в соответствии с обозначениями, аналогичными языку Си. Например:

;

; if { Length > MaxLength } {

;

mov

ax,[Length]

cmp

ax,[MaxLength]

jng

LengthIsLessThanMax

. . .

 

jng

EndMaxLengthTest

;

 

;} else {

;

LengthIsLessThanMax:

. . .

;

;}

;

EndMaxLengthTest:

7.22. Путают операнды в памяти и непосредственные

Программа на ассемблере может ссылаться либо на переменную памяти по смещению, либо на значение, хранящееся в этой переменной.

Например, смещение переменной в памяти размером в слово MemLoc представляет собой константу 5002, которую можно получить с помощью оператора OFFSET. Например, инструкция

mov bx,OFFSET MemLoc

загружает значение 5002h в регистр bx. Значение 5002h представляет собой непосредственный операнд. Другими словами, оно встроено непосредственно в инструкцию и не изменяется.

Значением MemLoc является 1234h. Оно считывается из памяти со смещением 5002h в сегменте данных. Один из способов считывания данного значения состоит в загрузке в регистр bx, si, di или bp смещения MemLoc и использовании данного регистра для адресации к памяти. Инструкции

mov bx,OFFSET MemLoc mov ax,[bx]

загружают значение MemLoc в регистр ax. Значение MemLoc можно также загрузить непосредственно в ax с помощью инструкции

mov ax,MemLoc

58

или

mov ax,[MemLoc]

Здесь значение 1234h получается как прямой, а не как непосредственный операнд: инструкция mov использует встроенное в нее смещение 5002h и загружает в ax значение по смещению 5002h, которое в данном случае равно 1234h.

Часто встречающейся ошибкой является то, что часто забывают использовать операцию offset, например:

mov si,MemLoc,

где нужно использовать смещение MemLoc. На первый взгляд, данная строка не выглядит неправильной, и так как MemLoc это переменная размером в слово, то эта строка не приведет к ошибке ассемблирования. Однако при выполнении в si будут загружены содержащиеся в переменной MemLoc данные (1234h), а не ее смещение (5002h) и результаты будут непредсказуемы.

Надежного способа избежать этой проблемы нет, но можно принять за правило заключать все ссылки на память в квадратные скобки. Когда перед ссылками на адресные константы будет указываться префикс OFFSET, а ссылки на память заключаться в квадратные скобки, это устранит двусмысленность и неопределенность при использовании имен переменных памяти. При таком соглашении работа инструкций

mov si,offset MemLoc

и

mov si,[MemLoc]

становится совершенно понятной, в то время как инструкция mov si,MemLoc

будет настораживать.

Библиографический список

1.Зубков С.В. Assembler для DOS, Windows и UNIX. / С.В. Зубков 11-е изд.,

стер. М.: ДМК Пресс; СПб.: Питер, 2010. 640 с.

2.Бурдаев О.В. Ассемблер в задачах защиты информации / О.В. Бурдаев, М.А. Иванов, И.И. Тетерин Под ред. И.Ю. Жукова. – 3-е изд., стер. – М.: КУДИЦ-

ОБРАЗ, 2008. – 544 с.

59

3. Абель Питер. Язык и программирование для IBM PC. / Питер Абель. Издво КОРОНА-Век, 2009.

60

Источник: https://studfile.net/preview/16407385/