Перевод с десятичного в двоичный на ассемблере. Перевод десятичных чисел в шестнадцатиричное - Assembler

1. Базовые системы счисления. Объявления данных в Ассемблере

Цель работы: ознакомление студентов с системами счисления – двоичной, восьмеричной, шестнадцатеричной; представлением данных в памяти компьютера, директивами выделения памяти.

Теоретическая часть

Наименьшая единица информации, которую можно сохранить в компьютере – это бит (eng. bit - bi nary digit ), т.е. 0 или 1. Бит – это атом информации, он не может быть разделен. Биты группируются по 8 и образуют байт. Информация, которой манипулирует компьютер – это строка бинарных чисел. Из 8 битов можно сформировать 256 комбинаций. Эти комбинации используются для того, чтобы закодировать большие и малые буквы, цифры, специальные символы.

Для измерения информации на компьютере используются величины:

1 Килобайт = 1 Кбайт = 2 10 байтов = 1024 байтам;

1 Мегабайт = 1 Мбайт = 2 20 байтов = 1024 Кбайтам;

1 Гигабайт = 1 Гбайт = 2 30 байтов = 1024 Мбайтам.

Системы счисления

Система счисления – это множество правил и цифр представления чисел. Для любой позиционной системы счисления число цифр для представления равно основанию системы счисления, например, для двоичной системы основанием является число 2, следовательно, для представления чисел нужны две цифры 0 и 1, для шестнадцатеричной системы счисления это 0, 1, 2, …, 9, A, B, C, D, E, F, где буквы соответствуют значениям 10, 11, 12, 13, 14 и 15 соответственно.

Чтобы различать системы счисления, в конце числа ставится буква: B – для двоичного числа, Q – для восьмеричного числа, D – для десятеричного числа и H – для шестнадцатеричного. Для десятеричного числа указывать D не обязательно.

Если число записано в b–ричной системе счисления в виде

Nr(b) = C n C n-1 C n-2 … C 2 C 1 C 0 , D 1 D 2 D 3 … ,

то в десятеричной системе счисления его значение можно представить в виде суммы цифр, умноженных на основание системы счисления в степени равной номеру позиции цифры в числе (нумерация начинается с 0, справа налево):

Nr(10) = C n *b n +C n-1 *b n-1 +…+C 2 *b 2 +C 1 *b 1 +C 0 *b 0 +D 1 *b -1 +D 2 *b –2 +D 3 *b –3 +...

Например:

Пусть даны два бинарных числа 11b, 1100011b. Переведем эти числа в десятеричную систему счисления:

11b =1*2 1 +1*2 0 =3;

11100011b = 1*2 7 +1*2 6 +1*2 5 +0*2 4 +0*2 3 +0*2 2 +1*2 1 +1*2 0 = 227.

Рассмотрим примеры перевода восьмеричного числа в десятичную систему счисления:

11q = 1*8 1 +1*8 0 = 9;

210q =2*8 2 +1*8 1 +0*8 0 =136.

Пример перевода шестнадцатеричных чисел в десятичные:

11h = 1*16 1 +1*16 0 =17;

CA0h= C*16 2 +A*16 1 +0*16 0 = 3232

Для перевода чисел из десятичной системы в двоичную или шестнадцатеричную применяется целое деление. Число делится на основание системы счисления пока не получится неделимый остаток. Полученное от деления частное снова делится и процесс завершается, когда частное тоже становится неделимым. Полученные при делении остатки записываются в обратном порядке. На схеме показан перевод числа 25 в двоичную систему счисления, в результате которого получаем число 11001b, а также перевод числа 418 в шестнадцатеричную систему счисления, в результате которого получаем число 1A2h, учитывая, что цифра десять - это A.

Для перевода чисел из шестнадцатеричной системы в двоичную и обратно используется следующий факт: каждой шестнадцатеричной цифре соответствует четырехбитовое двоичное число и наоборот, как это представлено в таблице. Следовательно, при переводе из шестнадцатеричной системы в двоичную надо для каждой шестнадцатеричной цифры записать её двоичный код, а при обратном переводе двоичное число разбивается справа налево на группы по четыре цифры и для них записывается шестнадцатеричное соответствие.

Таблица соответствия шестнадцатеричных цифр и двоичных чисел.

Например, переведем число 1FDh в двоичное представление:

1FDh = 0001-1111-1101b = 111111101b

Переведем двоичное число 1110100101b в шестнадцатеричное представление: 0011-1010-0101b = 3A5.

Представление целых чисел в памяти компьютера

Для представления информации на компьютере используют двоичную систему счисления. Для хранения целых чисел используется строго фиксированное число битов: 8, 16, 32, 64. На n бинарных позиций можно записать целое число со знаком в диапазоне от -2 n-1 до 2 n-1 -1. Позиции нумеруются от 0 до n-1 справа налево. Например, число 67 в восьми двоичных позициях будет представлено как 01000011b. Числа без знака можно представить в диапазоне 0 до 2 n -1.

Целое число может храниться в виде прямого или дополнительного кода. Для представления знака числа используется бит, называемый знаковым. Он находится в позиции n-1 и является старшим битом числа. Для положительных чисел этот бит равен нулю, для отрицательных – единице.

Прямой код используется для хранения положительных чисел или чисел без знака.

Дополнительный код используется для хранения отрицательных чисел. Для получения представления числа в дополнительном коде сначала находится прямой код модуля числа, затем его обратный код. Обратный код получается инверсией каждого разряда в двоичном представлении числа: 0 преобразуется в 1, а 1 – в 0. На последнем шаге к обратному коду прибавляется 1.

Например, для представления числа -65 имеем:

01000001b прямой код числа +65

10111110b обратный код

10111111b дополнительный код числа -65

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

Типы данных

BYTE . Этот тип данных занимает 1 байт (8 битов). При помощи этого типа можно зашифровать целое число со знаком в диапазоне от -128 до +127 или без знака в диапазоне от 0 до 255, любой ASCII–символ, который также кодируется целым числом. Директива определения – DB (Define Byte).

WORD . Этот тип данных занимает 2 байта (16 битов). В переменную данного типа можно поместить целое число в диапазоне от -32768 до+32767 или от 0 до 65535, два ASCII–символа или относительный адрес памяти типа near. При этом запись в память производится следующим образом: младшая часть числа располагается по младшему адресу, а старшая – по старшему. Это справедливо и для других типов данных. Например, если целое шестнадцатеричное число 1234h расположено по адресу 1000h, то младшая часть 34h будет расположена по адресу 1000h, а 12h – по адресу 1001h. Директива определения – DW (Define word).

DWORD – 4 байта (2 слова) может вместить целое 32–битное число со знаком или без знака, число с плавающей точкой, 32–разрядный адрес памяти или 4 ASCII–символа. При хранении адреса адрес сегмента располагается в двух старших байтах, а смещение – в двух младших байтах памяти. Директива определения – DD (Define Double word).

QWORD – 8 байтов. Может быть целым знаковым или беззнаковым, числом или числом с плавающей точкой двойной точности. Директива определения – DQ (Define Quad).

T EN-BYTES – 10 байтов. Используется для хранения данных в основной памяти или в сопроцессоре. Может быть упакованным двоично–десятичным числом, расширенным целым числом или расширенным числом с плавающей точкой. Директива определения - DT (Define Ten bytes).

Общий синтаксис определения данных:

< имя > < тип > < список значений >

< имя > < тип > < число > dup (выражение ),

где имя – идентификатор, тип – одна из рассмотренных выше директив выделения памяти, список значений – список, который может содержать символьные или числовые константы. Он может также содержать символ ? , если значение не определено, или адрес – имя переменной или метку, строку ASCII–символов, заключенных в кавычки или апострофы. Директива dup предписывает повторение значений, определяемых выражением, заданное <число> раз. Выражение может быть константой, константами, объединенными знаками арифметических операций, списком значений или символом ? , если значение не определено.

Например,

var_a db 2 dup (0, 3 dup (1)) ; эквивалентно var_a db 0,1,1,1,0,1,1,1 var_b db 1, 2, 3, ?, ? adr_a dw var_a adr_b3 dd var_b+3

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

m1 db 4 , 5 , 1 , 6 ; 4*1=4 байта m2 db “xzyqw” ; 5*1=5 байтов m3 dw 12 dup(?) ; 12*2=24 байта m4 dd 345h , 234h ; 2*4=8 байтов

m1 db 4, 5, 1, 6 ; 4*1=4 байта m2 db “xzyqw” ; 5*1=5 байтов m3 dw 12 dup(?) ; 12*2=24 байта m4 dd 345h, 234h ; 2*4=8 байтов

Общее количество байтов, выделенных данными директивами, равно 41 байту. Переменная m1 располагается по относительному адресу 00h, m2 – 04h, m3 – 09h, а m4 – 021h.

Индивидуальные задания:

1. Перевести в двоичную, шестнадцатеричную и восьмеричную системы счисления десятеричные числа:

1)42;31;113 5 )46;35;119 9 ) 49;30;103 13 )29;37;97
2 )45;81;89 6)66;25;110 10 )19;53;101 14 )21;87;98
3 )12;38;118 7 )17;63; 96 11)34;50;107 1 5) 28;45;130
4 )11;43;67 8 )13;69;88 1 2 )14;70;99 16)15;72;100

2. Перевести в двоичную систему счисления шестнадцатеричные числа:

1)A45;12;56B 5)7C;72EB;31DB 9)34A;6AB;9AD 13)2B9;6F1;81B
2)1EF3;5AB;46F 6)3EB;4D8;A61 10)5AB;79F;AB8 14)7CD;2A1;B53
3)A56;5E9;CDE 7)6A3;9D0;8BE 11)9A;4DE;EF7 15)10B;87F;CD9
4)3B8;DE1;BAE 8)BC;7F9;78A 12)AB;8E4;C17 16)38E;9C7;B89

3. Перевести в восьмеричную и шестнадцатеричную системы счисления бинарные числа:

1) 00101011; 00100110;
01110011
5 ) 11110010; 01101010;
11111100;
9 ) 10000101; 11100010;
11001011
13 ) 00011101; 11111001;
00111101
2 ) 01100001; 01101110;
11110011
6) 00110110; 00111011;
10001100
10 ) 00011101; 01010110;
10110010
14 ) 00011100; 01001100;
01101110
3) 11100100; 01011100; 11000001 7 ) 11010010; 01001100; 11000111 11) 11100010; 10100001; 10001110 1 5 ) 10101001; 11010101; 111001100
4 ) 00001111; 10100101; 10010001 8 ) 11100000 11111000; 01000011 1 2 ) 10100101; 01101100; 11100001 16) 11100111; 01100101; 10110010;

4. Представить в дополнительном коде следующие числа:

1)-42;-31;-96 5)-46;-35;-94 9) -49;-30;-103 13)-29;-37;-97
2)-52;-41;-93 6)-66;-25;-85 10)-19;-53 ; -101 14)-21;-87;-98
3)-12;-38;-93 7)-17;-63;-99 11)-34;-50;-94 15)-28;-45;-95
4)-11;-43;-67 8)-13;-69;-88 12)-14;-70;-99 16)-15;-72;-89

5. Даны следующие определения переменных:

1) a db 45,16,76,-6
b db “abcd”
c dw 15 dup(0),3,3
d dd 345h
2) a dd 2,24
b db “aaa”,-8,23h,11101b
c db 6 dup(0), 45, 6
d dw -7,4Dh,8 dup(0)
3) a db “Salut”,10,13
b db -16,-20,13h,2 dup(0)
c dw 62,34,-15
d dd 456C9h,4567
4) a dd 92,45h,90,-54,-67
b db 10 dup(‘$’),10,13
c db “amdto”,10,13,’$’
d dw 5 dup(?),7,-80h
5) a db “lucrarea_1”,10,13
b db 2 dup(0)
c dw 38,-15,78,41,12
d dd 678EFh,3489,456
6) a db 12,24,”sss”
b db “ab”,-8,23h
c dd 6 dup(0),45
d dw -7,5 dup(0)
7) a db 35,53
b db 10 dup(‘ ’),10,13,“$”
c dw 5 dup(0)
d dd 555h
8) a db 34,6,3,-8,-2
b db “Hello”,‘$’
c dw 6 dup(0),‘$’,10,13
d dw -68,46h,7 dup(0)
9) a db 45,16
b db 5 dup(?),10,13,“$”
c dw 55 dup(0)
d dd 34567h
10) a db 76,87,92,45h
b db 20 dup(‘$’),10,13
c db “qwert”
d dw 10 dup(0)
11) a dd 78,34,67
b db “Rezultat”,‘$’
c db 16 dup(0),‘$’,10,13
12) a db 73,74,75,77,78,-67
b db 15 dup(‘?’),10,13
c dd 777h
13) a db 24,76,-56
b db “abc”,11101b
c dd 45,4 dup(?)
d dw 4 dup(0),8,3
14) a db “testul_nr_2”,13,10
b db -18,-22,18h,2 dup(0)
c dw 81,-16,44,18
d dd 568ABh
15) a dd 87,45h,-9
b db 10 dup(?)
c db “test_1$”
d dw 4 dup(0),2,7
16) a db “Matematica”,10,13
b db 10,20h,2 dup(0)
c dw 60,30,-10,-20,-50
d dd 56789Bh

a) определить, сколько байтов выделено данными директивами;
b) определить адреса, по которым располагается каждая из переменных.

Здравствуйте! Имеется такая строка:

Var BD 2,2,3,3,4,4; 223344 десятичное 6-ти значное число в распакованном формате с повышенной точностью (ASCII формат)

Как это число 223344 перевести в шестнадцатиричное число? Я нашел такой код, который переводит из однозначного и двузначного десятичного числа в шестнадцатизначное:

; Вар. 17. Зад. 1. Написать подпрограмму для преобразования некоторого массива десятичных; ASCII байтов. в массив BCD байтов. С помощью этой подпрограммы обработать два массива; Для передачи параметров использовать стек. Name Program ; Описание констант;Описание переменных Data segment x1 db 2h db 1h db 3h db 1h db 4h db 1h ; числа в ASCII-формате y1 db 3 dup (?) ; массив в BCD-формате x2 db 8h ;98 db 9h db 5h ;95 db 9h db 7h ;87 db 8h db 2h ;92 db 9h ; массив десятич. ASCII-байтов Y2 db 4 dup (?) ; массив десятич. BCD-байтов Data ends Stack SEGMENT DW 16 dup(?) StkTOp LABEL word Stack ends Code SEGMENT ASSUME CS: Code, DS: Data, ES: Data, SS: Stack ; Здесь описываются подпрограммы abc proc push bp mov bp, sp ; привязка к верхушке стека mov cx, ; чтение параметров из стека (кол-во чисел) mov di, ; адрес переменной Y1 mov si, ; адрес переменной Х1 M1: mov al, +1 ; загружаем первое число в ASCII-формате shl ax, 1 ; сдвигаем на 4 разряда в право shl ax, 1 shl ax ,1 shl ax, 1 or al, ;востонавливаем число которое запомнили mov , al ; записываем число в BCD-формате inc si ; переходим на другое число inc si inc di ; модифицируем адрес BCD - числа dec cx ; уменьшаем кол-во чисел jnz M1 ; если они не кончились то идем на M1 pop BP ret 6 abc endp ; Основная программа Start: mov AX, Data mov DS, AX mov ES, AX mov Ax, Stack mov SS, AX mov SP, offset StkTop ; загружаем параметры в стек по условию задачи mov ax, offset x1 ; загружаем адрес первого массива push ax mov ax, offset Y1 ; загружаем адрес результата push ax mov ax, 3 ; кол-во чисел push ax call abc ; вызов подпрограммы mov ax, offset x2 ; загружаем адрес второго массива push ax mov ax, offset Y2 ; загружаем адрес результата push ax mov ax, 4 ; кол-во чисел push ax call abc ; вызов подпрограммы code ends end start

Эта статья по большей части для совсем начинающих. Если вы хорошо разбираетесь в системах счисления, можете обратить внимание лишь на особенности синтаксиса ассемблера FASM в конце статьи.

На самом деле процессор работает только с двоичными числами, состоящими из единиц и нулей 🙂 В виде двоичных чисел хранятся и обрабатываются все данные и команды любой программы. Однако, двоичная запись чисел слишком громоздка и неудобна для человека, поэтому в программах на ассемблере используются и другие системы счисления: десятичная, шестнадцатеричная и восьмеричная.

Немного теории

Прежде всего разберёмся, в чём различие между системами счисления. Любое десятичное число можно представить в таком виде:

123 10 = 1·10 2 + 2·10 1 + 3·10 0

Индекс внизу обозначает, что это десятичное число. Цифра каждого разряда умножается на 10 в степени, равной номеру разряда, если считать с нуля справа налево. В более общем виде:

abc r = a·r 2 + b·r 1 + c·r 0 ,

где a, b и с — какие-то цифры, а r — основание системы счисления. Для десятичной системы r = 10, для двоичной — r = 2, для троичной r = 3 и т.д. Например, то же самое число в других системах:

443 5 = 4·5 2 + 4·5 1 + 3·5 0 = 4·25 + 4·5 + 3·1 = 123 10 (пятеричная система)

173 8 = 1·8 2 + 7·8 1 + 3·8 0 = 1·64 + 7·8 + 3·1 = 123 10 (восьмеричная система)

1111011 2 = 1·2 6 + 1·2 5 + 1·2 4 + 1·2 3 + 0·2 2 + 1·2 1 + 1·2 0 = 1·64 + 1·32 + 1·16 + 1·8 + 0·4 + 1·2 + 1·1 = 123 10 (двоичная система)

Шестнадцатеричная система

В шестнадцатеричной системе для обозначения цифр больше 9 используются буквы A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Например:

C7 16 = 12·16 1 + 7·16 0 = 12·16 + 7·1 = 199 10

Удобство шестнадцатеричной системы в том, что в неё очень легко можно переводить двоичные числа (и в обратную сторону тоже). Четыре разряда двоичного числа (тетрада) представляются одним разрядом шестнадцатеричного. Для перевода достаточно разбить число на группы по 4 бита и заменить каждую тетраду соответствующей шестнадцатеричной цифрой.

Двоичная
тетрада
Шестнадцатеричная
цифра
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F

Для записи одного байта требуется всего 2 шестнадцатеричные цифры:

0101 1011 2 = 5B 16

0110 0000 2 = 60 16

1111 1111 2 = FF 16

Восьмеричная система

Восьмеричная система также удобна для представления двоичных чисел, хотя она используется намного реже, чем шестнадцатеричная. Для быстрого перевода надо разбить двоичное число на группы по 3 разряда (триплеты или триады).

Двоичная
триада
Восьмеричная
цифра
000 0
001 1
010 2
011 3
100 4
101 5
110 6
111 7

Например: 001 110 101 2 = 165 8

Синтаксис ассемблера FASM

По умолчанию, число в программе воспринимается ассемблером как десятичное. Чтобы обозначить двоичное число, необходимо к нему в конце добавить символ ’b’ . Восьмеричное число обозначается аналогично с помощью символа ’o’ . Для записи шестнадцатеричного числа FASM поддерживает 3 формы записи:

  • перед числом записываются символы ’0x’ (как в C/C++);
  • перед числом записывается символ ’$’ (как в Pascal);
  • после числа записывается символ ’h’ . Если шестнадцатеричное число начинается с буквы, необходимо добавить в начале ноль (иначе непонятно, число это или имя метки).

Этот синтаксис используется как при объявлении данных, так и в командах. Вот примеры записи чисел во всех четырёх системах:

mov ax , 537 ;Десятичная система mov bl , 11010001b ;Двоичная система mov ch , 57o ;Восьмеричная система mov dl , $ C2 ;\ mov si , 0x013A ; \ mov ah , 18h ; / Шестнадцатеричная система mov al , 0FFh ;/ mov al , FFh ;Ошибка!

mov ax,537 ;Десятичная система mov bl,11010001b ;Двоичная система mov ch,57o ;Восьмеричная система mov dl,$C2 ;\ mov si,0x013A ; \ mov ah,18h ; / Шестнадцатеричная система mov al,0FFh ;/ mov al,FFh ;Ошибка!