D = dn-1dn-2…d1d0 - исходное n-разрядное число
D = d0 + d1*q + d2*q2 + d3*q3 + … + dn-1*qn-1
Схема Горнера:
D = (…(dn-1 *q + dn-2)*q + dn-3)*q + …d1)*q + d0
Алгоритм преобразования массива цифр:
for(s = 0, i = n-1; i >= 0; i--)
s = s*q + d[i];
Алгоритм преобразования ASCII-строки цифр, размещенных в массиве char m[];
for(s = 0, register char p = m, i = n; i!= 0; i--)
s = s*q + digit(*p++);
Значения s, получаемые в ходе трассировки при преобразовании числа 1234510 : 0, 1, 12, 123, 1234, 12345
При q <= 10 digit(chr) = chr - '0';
Для q > 10 проводится дополнительный анализ ASCII-цифр, учитывающий кодирование цифр, больших девяти, либо используется таблица преобразования (d=tbl[chr-‘0’]).
; Таблица для шестнадцатиричных
tbl db 0,1,2,3,4,5,6,7,8,9 ; от кодов 30h..39h (’0123456789’)
db 7 dup (?) ; от кодов 3Ah..40 (’:;<=>?@’)
db 10,11,12,13,14,15 ; от кодов 41h..41h (‘ABCDEF’)
Дома: написать фрагмент преобразования ASCI-строки в 16-ричное число, учитывающий возможность строчных и прописных букв A..F, a..f.
Для q = 2k вместо умножения используется сдвиг:
s <<= k, s |= digit(*p++);
Для q = 2 процесс может быть упрощен еще больше
![]() |
PDP-11: S - R1, P - R2, ch - R0, i – R3 | x86: S - DX, P - SI, ch - AL, i - CX | ||||
CLR | R1 | XRA | DX, DX | ||
MOV | #M, R2 | LEA | SI, M | ||
MOV | #5, R3 | MOV | CX, 5 | ||
L: | MOVB | (R2)+, R0 | L: | MOV | AL, [SI] |
INC | SI | ||||
ROR | R0 | ROR | AL, 1 | ||
ROL | R1 | ROL | DX | ||
SOB | R3, L | LOOP | L |
Преобразование числа в строку
d0 = D mod q
d1 = (D div q) mod q
d2 = ((D div q) div q) mod q
…
Алгоритм вывода ASCII-строки цифр
for(i = n; i!= 0; i--)
putc(asc(d%q)), d = d / q;
Для q <= 10 asc(x) = x + '0'.
Обработка данных с повышенной точностью
Сложение
sm-1,…,s1,s0 + am-1,…,a1,a0 ----------- sm-1,…,s1,s0 |
|
#define BITLEN 64
#define WLEN BITLEN/16
unsigned int
ma[WLEN] = // массив a0,a1,a2,a3
{0xffff, 0x0001, 0x8000, 0xAAAA},
ms[WLEN] = // массив s0,s1,s2,s3
{0x0001, 0x0002, 0x8000, 0x0001},
*pa, *ps, // сканеры массивов
i, cf; // счетчик и перенос
unsigned long l; // сумма двух int
main()
{ for(pa=ma, ps=ms, i=WLEN, cf=0;
i>0; i--)
{ l = (unsigned long)*pa++
+ *ps + cf;
*ps++ = (unsigned int)l;
cf = *((int *)(&l)+1);
}
}
Дома: написать на 2-х ассемблерах Организация подпрограмм
subr(p_1,…,p_n);
y = func(q_1,…,q_m) + x;
Реализация:
1) Пересылка p_1,…,p_n в программно-доступные компоненты, выделяемые для представления формальных параметров процедуры subr.
2) Вызов subr так, чтобы можно было возвратиться к продолжению программы.
3) Пересылка q_1,…,q_m в программно-доступные компоненты, выделяемые для представления формальных параметров.
4) Вызов func так, чтобы можно было возвратиться в точку подсуммирования к значению func переменной x.
Основные элементы данных:
АВ - адрес возврата;
МХАВ - место хранения АВ;
ТВ - точка входа в ПП.
Способы сохранения адреса возврата:
1. В ячейке памяти, принадлежащей подпрограмме.
Пример(PDP-8: МХАВ==mem(ТВ)) :
вызов subr: а) mem(ТВ) = PC; б) PC = ТВ+1
возврат: PC = mem(ТВ) // jump с косвенной адресацией через метку ПП
2. Через стек
Пример(I8086) :
вызов subr:
а) вычисление ТВ и продвижение IP к следующей команде (АВ в IP);
б) сохранение АВ и переход:
// при внутрисегментном переходе
mem(--SP) = IP; IP = ТВ
// при межсегментном переходе
mem(--SP) = CS; mem(--SP) = IP
CS:IP = ТВ
возврат:
// внутрисегментный
IP = mem(SP++);
// межсегментный
IP = mem(SP++); CS = mem(SP++)
После восстановления АВ в IP или CS:IP возможна модификация SP для удаления параметров, передаваемых через стек
3. Через регистр.
Пример(PDP-11):
вызов subr:
а) вычисление ТВ и продвижение PC к следующей команде;
б) сохранение регистра адреса возврата:
mem(--SP) = Ri
в) сохранение адреса возврата и переход:
Ri = PC ; PC = ТВ.
Частный наиболее используемый в PDP-11 случай - Ri = PC. При этом способ 3 вырождается в способ 2(через стек).
Передача параметров в процедуры
Через регистр
;===================================
; CPYRG - копирует R0 байтов памяти (R0 > 0)
; от адреса R1 в область памяти с адресом R2
; ===================================
CPYRG: MOVB (R1)+,(R2)+ ;
SOB R0, CPYRG ; ЦИКЛ
RETURN ; RTS PC
; Пример вызова CPYRG
SIZE1 = 30
M1: .BLKB SIZE1
M2: .BLKB SIZE1
. . . .
; CPYRG(M1,M2,SIZE1)
MOV #M1, R1
MOV #M2, R2
MOV #SIZE1, R0
CALL CPYRG ; JSR PC, CPYRG
;===================================
; CPYRG - копирует CX байтов памяти (CX > 0)
; от адреса SI в область памяти с адресом DI
; ===================================
CPYRG PROC NEAR
PUSH DS ; данные в одном
POP ES ; сегменте
CLD ; задать DF, чтобы ++
; повторить CX раз копирование
; do {*ES:DI++ = *DS:SI++;} while(--CX!= 0)
REP MOVSB ; скопировать
RET
CPYRG ENDP
Передача параметров через область памяти, принадлежащую процедуре
Фаза вызова: Подпрограмма:
·
|
параметров в область
формальных параметров
· Вызов подпрограммы
|
Проблема видимости при размещении ПП и фазы вызова в разных модулях
В PDP-11:
:: - разделитель в объявлении глобальной метки;
.GLOBL список имен - объявление имен глобальными
В x86:
PUBLIC список имен - объявление имен для помещение в таблицу obj-файла
EXTRN список имен – объявление для разрешение ссылок на неописанные имена
;===================================
; CPYAR - копирует CNT байтов памяти
; от адреса P1 в область памяти с адресом P2
; ===================================
CNT:: .WORD
P1:: .WORD
P2:: .WORD
CPYAR:: MOVB @P1, @P2
INC P1
INC P2
DEC CNT
BNE CPYAR
RETURN
;Вызов для копирования M1 в M2
.GLOBL CNT, P1,P2,CPYAR
MOV #M1, P1
MOV #M2, P2
MOV #SIZE1, CNT
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 |



