Double word to bytes

First thing, always understand your data, the x86 memory is addressable by bytes. It doesn’t matter what kind of logical structure you use to write the data into the memory, if anybody else is watching the memory content, and they don’t know about your logical structure, they see only bytes.

a dd 12345678h,1A2B3Ch,78h

So this compiles as 12 (3 * 4) bytes:

78 67 34 12 3C 2B 1A 00 78 00 00 00

To condense such array by removing zeroes you don’t even need to work with double words, just copy it byte by byte (voluntarily dropping away your knowledge that it was meant as double word array originally), skipping zero values.

code segment
start:
    mov ax,data
    mov ds,ax

    lea     si,[a]      ; original array offset
    lea     di,[n]      ; destination array offset
    mov     cx,l        ; byte (!) length of original array

    repeta:
        ; load single byte from original array
        mov     al,[si]
        inc     si
        ; skip zeroes
        test    al,al
        jz      skipping_zero
        ; store non-zero to destination
        mov     [di],al
        inc     di
    skipping_zero:
        loop    repeta

    ; fill remaining bytes of destination with zeroes - init
    xor     al,al
    lea     si,[n+l]    ; end() offset of "n"
    ; jump first to test, so filling is skipped when no zero
    jmp     fill_remaining_test

    fill_remaining_loop:
        ; clear one more byte in destination
        mov     [di],al
        inc     di
    fill_remaining_test:
        ; test if some more bytes are to be cleared
        cmp     di,si       ; current offset < end() offset
        jb      fill_remaining_loop

    ; exit back to DOS
    mov ax,4C00h
    int 21h

code ends
end start

But this is complete rewrite of your code, unfortunately, so I will try to add some explanations what’s wrong in yours.

About MUL, and especially about multiplying by power of two value:

    mov     bx,si   ; bx = si (index into array?)
    mul     pat     ; dx:ax = ax * word(4)

As you can see, the mul doesn’t use either bx, or si, and it results into 32 bit value, split into dx (upper word) and ax (lower word).

To multiply si by 4 you would have either to do:

    mov     ax,si   ; ax = si
    mul     [pat]   ; dx:ax = ax * word(4)

Or simply exploiting that computers are working with bits, and binary encoding of integer values, so to multiply by 4 you need only to shift bit values in the value by two positions «up» (left).

    shl     si,2    ; si *= 4 (truncated to 16 bit value)

But that destroys original si («index»), so instead of doing this people usually adjust the loop increment. You will start with si = 0, but instead of inc si you would do add si,4. No multiply needed any more.


add bx,1 hurts my eyes, I prefer inc bx in human Assembly (although on some generations of x86 CPUs the add bx,1 was faster, but on modern x86 the inc is again fine).

mov al,byte ptr a[si]+1 is very weird syntax, I prefer to keep things «Intel-like» simple, ie. mov al,byte ptr [si + a + 1]. It’s not C array, it’s really loading value from memory from address inside the brackets. Mimicking C-array syntax will probably just confuse you over time. Also the byte ptr can be removed from that, as al defines the data width already (unless you are using some MASM which enforces this upon dd array, but I don’t want to touch that microsoft stuff with ten foot pole).

Same goes for mov n[bx],al = mov [n + bx],al or mov [bx + n],al, whichever makes more sense in the code.

But overall it’s a bit unusual to use index inside loop, usually you want to convert all indexes into addresses ahead of loop in the init part, and use final pointers without any calculation inside loop (incrementing them by element size, ie. add si,4 for double words). Then you don’t need to do any index multiplication.

Especially in 16 bit mode, where the addressing modes are very limited, in 32/64b mode you can at least multiply one register with common sizes (1, 2, 4, 8), ie. mov [n + ebx * 4],eax = no need to multiply it separately.

EDIT: there’s no scale (multiply by 1/2/4/8 of «index» part) in 16b mode available, the possible example [si*4] would not work.


New variant storing bytes from most-significant dword byte (ie. reversing the little-endian scheme of x86 dword):

code segment
start:
    mov     ax,data
    mov     ds,ax
    lea     si,[a]      ; original array offset
    lea     di,[n]      ; destination array offset
    mov     cx,l1       ; element-length of original array

    repeta:
        ; load four bytes in MSB-first order from original array
        ; and store only non-zero bytes to destination
        mov     al,[si+3]
        call    storeNonZeroAL
        mov     al,[si+2]
        call    storeNonZeroAL
        mov     al,[si+1]
        call    storeNonZeroAL
        mov     al,[si]
        call    storeNonZeroAL
        ; advance source pointer to next dword in array
        add     si,4
        loop    repeta

    ; Different ending variant, does NOT zero remaining bytes
    ; but calculates how many bytes in "n" are set => into CX:
    lea       cx,[n]      ; destination begin() offset
    sub       cx,di
    neg       cx          ; cx = number of written bytes into "n"

    ; exit back to DOS
    mov ax,4C00h
    int 21h

; helper function to store non-zero AL into [di] array
storeNonZeroAL:
    test    al,al
    jz      ignoreZeroAL
    mov     [di],al
    inc     di
ignoreZeroAL:
    ret

code ends
end start

Written in a way to keep it short and simple, not for performance (and I strongly suggest you to aim for the same, until you feel really comfortable with the language, it’s difficult enough for beginner even if written in simple way without any expert-trickery).

BTW, you should find some debugger which works for you, so it would be possible for you to step instruction by instruction and watch how that resulting values in «n» are being added, and why. Or you would probably notice sooner that the bx+si vs mul don’t do what you expect and the remaining code is operating on wrong indices. Programming in Assembly without debugger is like trying to assemble a robot blindfolded.

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

Преобразовать больший тип в меньший гораздо проще — достаточно отбросить старшую часть. Но такое преобразование небезопасно и может привести к ошибке. Например, если значение слова без знака больше 255, то сделав из него байт, вы получите некорректное значение. Будьте внимательны, если вы используете такие трюки в своей программе.

Преобразование типов без знака

Преобразование типов выполняется по-разному для чисел со знаком и без. Для преобразования чисел без знака необходимо просто заполнить все старшие биты нулями. Например, так будет выглядеть преобразование байта в слово:

Такое преобразование можно выполнить с помощью обычной команды MOV (x объявлен как байт):

    mov bl,[x]
    mov bh,0     ;BX = x
;Или вот так:
    mov bl,[x]
    sub bh,bh    ;BX = x

Но кроме того в системе команд процессора существует специальная команда — MOVZX (копирование с нулевым расширением). Первый операнд команды имеет размер 16 бит (слово), а второй — 8 бит (байт). Тот же результат можно получить так:

Преобразование типов со знаком

Для чисел со знаком всё немного сложнее. Если мы просто заполним старшую часть нулями, то результат будет положительным, а это не всегда верно. Поэтому преобразование выполняется путём копирования знакового бита на всю старшую часть. То есть для положительного числа со знаком старшая часть будет заполняться нулями, а для отрицательного — единицами:

Для такого преобразования предназначена команда MOVSX (копирование со знаковым расширением). Первый операнд — слово, второй операнд — байт. Например (y объявлен как байт):

Существуют ещё две команды для преобразования типов со знаком: CBW (Convert Byte to Word — преобразовать байт в слово) и CWD (Convert Word to Double word — преобразовать слово в двойное слово). У этих команд нет явных операндов. Команда CBW преобразует байт, находящийся в регистре AL, в слово в регистре AX. Команда CWD преобразует слово, находящееся в регистре AX, в двойное слово в регистрах DX:AX. Эти команды удобно использовать вместе с командами умножения и деления. Например:

    mov al,[y]
    cbw          ;AX = y
    cwd          ;DX:AX = y

Пример программы

Допустим, требуется вычислить значение формулы x = (a + b) / c. Все числа со знаком. Размер x — двойное слово, размер a — байт, размер b и c — слово.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use16                 ;Генерировать 16-битный код
org 100h              ;Программа начинается с адреса 100h
 
    movsx ax,[a]      ;AX = a
    add ax,[b]        ;AX = a+b
    cwd               ;DX:AX = a+b
    idiv [c]          ;AX = (a+b)/c, в DX остаток
    cwd               ;DX:AX = (a+b)/c
    mov word[x],ax    ;
    mov word[x+2],dx  ;/ x = DX:AX
 
    mov ax,4C00h      ;
    int 21h           ;/ Завершение программы
;-------------------------------------------------------
a   db -55
b   dw -3145
c   dw 100
x   dd ?

Упражнение

Напишите программу для вычисления формулы z = (x·y) / (x + y). Все числа со знаком. Размер x — байт, размер y — слово, размер z — двойное слово. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.

Следующая часть »

VlaDO5

0 / 0 / 0

Регистрация: 04.10.2018

Сообщений: 5

1

MASM

13.10.2018, 17:48. Показов 5894. Ответов 7

Метки нет (Все метки)


Студворк — интернет-сервис помощи студентам

Здравствуйте. Помогите пожалуйста, как dword/byte.
Вот пример как я делал, не понимаю в чем ошибка. Заранее спасибо.

Assembler
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
#include "pch.h"
#include <iostream>
 
int main()
{   
    char b1 = 0x10; // byte
    int dw1 = 0x12345678; // dword
    short rez4, ost4;
 
    __asm {
        
        // dword/byte
        xor EAX, EAX
        mov BL, b1
        cbw
        mov EDX, dw1
        mov AX, DX
        shr EDX, 16
        div b1
        mov rez4, AX
        mov ost4, DX
        
    }
 
    return 0;
}



0



Модератор

Эксперт по электронике

8297 / 4200 / 1598

Регистрация: 01.02.2015

Сообщений: 13,065

Записей в блоге: 4

13.10.2018, 21:05

2

Загрузите байт в AL и последовательными инструкциями расширьте его до двойного слова, результат перенесите в какой нибудь регистр.
Потом загрузите делимое, расширьте его до четверного слова в регистровой паре.
Теперь делите.

О расширении регистров (имеется в виду знаки чисел) прочтите в главе 10 среди «деления» и «изменения размеров числа».
Электронный учебник



1



0 / 0 / 0

Регистрация: 04.10.2018

Сообщений: 5

13.10.2018, 22:43

 [ТС]

3

За объяснение спасибо. Пожалуйста не могли бы вы мне, отправить сам код который нужно написать в Ассемблере? Так как я пока не понимаю как это сделать.



0



Модератор

Эксперт по электронике

8297 / 4200 / 1598

Регистрация: 01.02.2015

Сообщений: 13,065

Записей в блоге: 4

13.10.2018, 22:59

4

Попробуйте прочесть два раздела главы 10. Станет легче.



0



VlaDO5

0 / 0 / 0

Регистрация: 04.10.2018

Сообщений: 5

14.10.2018, 17:56

 [ТС]

5

Assembler
1
2
3
4
5
6
7
8
9
10
11
//dword/byte
        mov AL, b1
        cbw           //AL --> AX
        mov BX, AX    //AX --> BX
        xor EAX, EAX       //EAX = 0
        mov EDX, dw1
        mov AX, DX
        shr EDX, 16   //лог. смещение вправо на 16
        div BX        //(dword/byte) --> BX
        mov rez4, AX
        mov ost4, DX



0



ФедосеевПавел

Модератор

Эксперт по электронике

8297 / 4200 / 1598

Регистрация: 01.02.2015

Сообщений: 13,065

Записей в блоге: 4

14.10.2018, 18:23

6

Можно так. А я бы попробовал

Assembler
1
2
3
4
5
6
7
8
9
mov al, b1
cbw
cwd
mov ebx, eax
 
mov eax, dw1
cdq
 
idiv ebx



1



Mikl___

Ушел с форума

Автор FAQ

15852 / 7433 / 996

Регистрация: 11.11.2010

Сообщений: 13,402

14.10.2018, 18:24

7

Лучший ответ Сообщение было отмечено ФедосеевПавел как решение

Решение

VlaDO5,

Assembler
1
2
3
4
5
6
7
8
9
10
11
char b1 = 0x10; // byte
int dw1 = 0x12345678; // dword
int rez4, ost4;  // dword
__asm {
          movs ebx,b1
          mov eax,dw1
          cdq
          idiv ebx 
          mov rez4,EAX
          mov ost4,EDX
          }



4



Модератор

Эксперт по электронике

8297 / 4200 / 1598

Регистрация: 01.02.2015

Сообщений: 13,065

Записей в блоге: 4

14.10.2018, 18:25

8

Точно, есть же копирование с расширением знака movs



0



This function block allows you to convert a variable WORD in two variables BYTE. The 8 high bits of In will be transferred to the operand MSB, low 8 bits will be transferred to the operand LSB.

Function lock
CODESYS: Not available
LogicLab: eLLabUtyLib

In (WORD) Variable to convert.

MSB (BYTE) MSB of the input value.

LSB (BYTE) LSB of the input value.

FB_WordToByte

Examples

How to use the examples.
In the example a variable WORD with value 16 # 1234 is transferred in two variables BYTE which will have value 16 # 12 and 16 # 34. In the example in language ST it is highlighted how the same operation is much simpler by writing it directly with the operands of the language.

LogicLab (Ptp114)

PROGRAM ST_WordToByte
VAR
    WData : WORD := 16#1234; (* Word data *)
    High : ARRAY[ 0..1 ] OF BYTE; (* MSB byte *)
    Low : ARRAY[ 0..1 ] OF BYTE; (* LSB byte *)
    WDec : WordToByte; (* Word decompress *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_WordToByte"
// *****************************************************************************
// This program shows the use of WordToByte function block.
// -----------------------------------------------------------------------------

    // -------------------------------------------------------------------------
    // DECOMPRESS WORD
    // -------------------------------------------------------------------------
    // Decompress word using the FB.

    WDec(In:=WData);
    High[0]:=WDec.MSB; //MSB byte
    Low[0]:=WDec.LSB; //LSB byte

    // -------------------------------------------------------------------------
    // DECOMPRESS WORD
    // -------------------------------------------------------------------------
    // The same operation as above executed directly using ST statements.

    High[1]:=TO_BYTE(WData/256); //MSB byte
    Low[1]:=TO_BYTE(WData); //LSB byte

// [End of file]

Was this article helpful?

Статья основана на материале xrnd с сайта asmworld (из учебного курса по программированию на ассемблер 16-битного процессора 8086 под DOS).

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

Преобразовать больший тип в меньший гораздо проще — достаточно отбросить старшую часть. Но такое преобразование небезопасно и может привести к ошибке. Например, если значение слова без знака больше 255, то сделав из него байт, вы получите некорректное значение. Будьте внимательны, если вы используете такие трюки в своей программе.

Преобразование типов без знака

Преобразование типов выполняется по-разному для чисел со знаком и без. Для преобразования чисел без знака необходимо просто заполнить все старшие биты нулями. Например, так будет выглядеть преобразование байта в слово:

Такое преобразование можно выполнить с помощью обычной команды MOV (x объявлен как байт):

    mov bl,[x]
    mov bh,0     ;BX = x
;Или вот так:
    mov bl,[x]
    sub bh,bh    ;BX = x

Но кроме того в системе команд процессора существует специальная команда — MOVZX (копирование с нулевым расширением). Первый операнд команды имеет размер 16 бит (слово), а второй — 8 бит (байт). Тот же результат можно получить так:

movzx bx,[x] ;BX = x

Преобразование типов со знаком

Для чисел со знаком всё немного сложнее. Если мы просто заполним старшую часть нулями, то результат будет положительным, а это не всегда верно. Поэтому преобразование выполняется путём копирования знакового бита на всю старшую часть. То есть для положительного числа со знаком старшая часть будет заполняться нулями, а для отрицательного — единицами:

Для такого преобразования предназначена команда MOVSX (копирование со знаковым расширением). Первый операнд — слово, второй операнд — байт. Например (y объявлен как байт):

movsx cx,[y] ;CX = y

Существуют ещё две команды для преобразования типов со знаком: CBW (Convert Byte to Word — преобразовать байт в слово) и CWD (Convert Word to Double word — преобразовать слово в двойное слово). У этих команд нет явных операндов. Команда CBW преобразует байт, находящийся в регистре AL, в слово в регистре AX. Команда CWD преобразует слово, находящееся в регистре AX, в двойное слово в регистрах DX:AX. Эти команды удобно использовать вместе с командами умножения и деления. Например:

    mov al,[y]
    cbw          ;AX = y
    cwd          ;DX:AX = y

Пример программы

Допустим, требуется вычислить значение формулы

$$x = frac{a + b}{c}$$

Все числа со знаком. Размер x — двойное слово, размер a — байт, размер b и c — слово.

use16                 ;Генерировать 16-битный код
org 100h              ;Программа начинается с адреса 100h
 
    movsx ax,[a]      ;AX = a
    add ax,[b]        ;AX = a+b
    cwd               ;DX:AX = a+b
    idiv [c]          ;AX = (a+b)/c, в DX остаток
    cwd               ;DX:AX = (a+b)/c
    mov word[x],ax    ;
    mov word[x+2],dx  ;/ x = DX:AX
 
    mov ax,4C00h      ;
    int 21h           ;/ Завершение программы
;-------------------------------------------------------
a   db -55
b   dw -3145
c   dw 100
x   dd ?

Упражнение

Напишите программу для вычисления формулы
$$z = frac{x cdot y}{x + y}$$
Все числа со знаком. Размер x — байт, размер y — слово, размер z — двойное слово. Проверьте работу программы в отладчике. Результаты можете выкладывать в комментариях.

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

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

Преобразование типов без знака

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

Преобразование беззнакового значения происходит просто. В программе на ассемблере для преобразования такого типа используется команда MOV:

mov dl,[a]

mov dh,0

;Другой вариант:

mov dl,[a]

xor dh,dh

;Вот еще один:

mov dl,[a]

sub dh,dh

;

a db 118

Также для беззнаковых преобразований в ассемблере есть специальная команда MOVZX (move with Zero-Extend, т.е. переместить с нулевым расширением). Она копирует содержимое операнда источника (регистр или значение в памяти) в операнд назначения (регистр). Старшая часть расширения заполняется нулями. Операнд назначения определяет размер расширения.

Преобразование командой MOVZX происходит так:

movzx cx,[b] ;CX = b

;

b db 193

Преобразование типов со знаком

Существует нюанс, касающийся старшего бита, который, как мы помним из Урока 8. Числа со знаком и без, является знаковым битом, то есть битом, определяющим, стоит перед числом знак «минус» или нет. Поэтому преобразования знакового числа происходит через прибавление старшей части и её заполнением знаковым битом. Говоря проще, если число было отрицательным, то старшая часть заполняется единицами, а если положительным – то нулями:

В ассемблере за преобразование типов знаковых значений отвечает команда MOVSX (Move with Sign-Extension, т.е. переместить со знаковым расширением). Она копирует содержание операнда источника (регистр или значение в памяти) в операнд назначения (регистр), расширяя значение знаковым битом:

Дополнительно в ассемблере есть еще команды для преобразования знаковых операндов: CBW – преобразует байт в слово (Convert Byte to Word) и CWD – преобразует слово в двойное слово (Convert Word to Double word). Они не получают явных операндов. Вместо этого CBW расширяет значение-байт в регистре AL в слово в регистре AX. В свою очередь CWD преобразует значение-слово в AX в двойное слово DX:AX. На практике обе команды часто сопутствуют операциями на умножении и деление.

Пример программы

Найдем решение формулы m = (a + 1) / (b – c). Все операнды со знаком. Размер m – слово, размер a – двойное слово, размер b – слово, размер c – байт.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

use16               ;Генерировать 16битный код

org 100h            ;Программа начинается с адреса 100h

    mov ax,[b]        ;AX = b

    movsx cx,[c]      ;CX = c

    sub ax,cx         ;AX = (b c)

    mov cx,ax         ;Запоминаем результат в CX

    mov ax,word[a]    ;AX = младшая часть a

    mov dx,word[a+2]  ;DX = старшая часть a

    add ax,1          ;

    adc dx,0          ;/DX:AX = (a + 1)

    idiv cx           ;AX = (a + 1) / (b c), в DX остаток

    mov [m],ax        ;m = AX, в DX остаток

    int 20h           ;Завершение программы

a dd 12299

b dw 128

c db 16

m dw ?

Упражнение

Теперь упражнение для самостоятельной работы. Закрепите пройденный урок написанием программы для решения формулы m = a^2 / (a + b). Все операнды со знаком. Размер a – слово, размеры b – байт, размер m – двойное слово. После компиляции откройте программу в Turbo Debugger, выполните все строки и проверьте, какое значение записалось по адресу переменной m. Результат отправьте в комментарии к уроку.

Целые числа


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

Первым делом необходимо выбрать систему счисления, наиболее подходящую для применения в конкретных устройствах. Для электронных устройств самой простой реализацией является двоичная система: есть ток — нет тока, или малый уровень тока — большой уровень тока. Хотя наиболее эффективной являлась бы троичная система. Наверное, выбор двоичной системы связан еще и с использование перфокарт, в которых она проявляется в виде наличия или отсутствия отверстия. Отсюда в качестве цифр для представления информации используются 0 и 1.

Таким образом данные в компьютере представляются в виде потока нулей и единиц. Один разряд этого потока называется битом. Однако в таком виде неудобно оперировать с данными вручную. Стандартом стало разделение всего потока на равные последовательные группы из 8 битов — байты или октеты. Далее несколько байтов могут составлять слово. Здесь следует разделять машинное слово и слово как тип данных. В первом случае его разрядность обычно равна разрядности процессора, т.к. машинное слово является наиболее эффективным элементом для его работы. В случае, когда слово трактуется как тип данных (word), его разрядность всегда равна 16 битам (два последовательных байта). Также как типы данных существую двойные слова (double word, dword, 32 бита), четверные слова (quad word, qword, 64 бита) и т.п.

Теперь мы вплотную подошли к представлению целых чисел в памяти. Т.к. у нас есть байты и различные слова, то можно создать целочисленные типы данных, которые будут соответствовать этим элементарным элементам: byte (8 бит), word (16 бит), dword (32 бита), qword (64 бита) и т.д. При этом любое число этих типов имеет обычное двоичное представление, дополненное нулями до соответствующей размерности. Можно заметить, что число меньшей размерности можно легко представить в виде числа большей размерности, дополнив его нулями, однако в обратном случае это не верно. Поэтому для представления числа большей размерности необходимо использовать несколько чисел меньшей размерности. Например:

  • qword (64 бита) можно представить в виде 2 dword (32 бита) или 4 word (16 бит) или 8 byte (8 бит);
  • dword (32 бита) можно представить в виде 2 word (16 бит) или 4 byte (8 бит);
  • word (16 бит) можно представить в виде 2 byte (8 бит);

Если A — число, B1..Bk — части числа, N — разрядность числа, M — разрядность части, N = k*M, то:

Например:

  • A = F1E2D3C4B5A69788 (qword)
  • A = 232 * F1E2D3C4 (dword) + 20 * B5A69788 (dword)
  • A = 248 * F1E2 (word) + 232 * D3C4 (word) + 216 * B5A6 (word) + 20 * 9788 (word)
  • A = 256 * F1 (byte) + 248 * E2 (byte) + … + 28 * 97 (byte) + 20 * 88 (byte)

Существуют понятия младшая часть (low) и старшая часть (hi) числа. Старшая часть входит в число с коэффициентом 2N-M, а младшая с коэффициентом 20. Например:

Байты числа можно хранить в памяти в различном порядке. В настоящее время используются два способа расположения: в прямом порядке байт и в обратном порядке байт. В первом случае старший байт записывается в начале, затем последовательно записываются остальные байты, вплоть до младшего. Такой способ используется в процессорах Motorola и SPARC. Во втором случае, наоборот, сначала записывает младший байт, а затем последовательно остальные байты, вплоть до старшего. Такой способ используется в процессорах архитектуры x86 и x64. Далее приведен пример:

Используя подобные целочисленные типы можно представить большое количество неотрицательных чисел: от 0 до 2N-1, где N — разрядность типа. Однако, целочисленный тип подразумевает представление также и отрицательных чисел. Можно ввести отдельные типы для отрицательных чисел от -2N до -1, но тогда такие типы потеряют универсальность хранить и неотрицательные, и отрицательные числа. Поэтому для определения знака числа можно выделить один бит из двоичного представления. По соглашению, это старший бит. Остальная часть числа называется мантиссой.

Если старший бит равен нулю, то мантисса есть обычное представление числа от 0 до 2N-1-1. Если же старший бит равен 1, то число является отрицательным и мантисса представляет собой так называемый дополнительный код числа. Поясним на примере:

Как видно из рисунка, дополнительный код равен разнице между числом 2N-1 и модулем исходного отрицательного числа (127 (1111111) = 128 (10000000) — |-1| (0000001)). Из этого вытекает, что сумма основного и дополнительного кода одного и того же числа равна 2N-1.

Из вышеописанного получается, что можно использовать только целочисленные типы со знаком для описания чисел. Однако существует множество сущностей, которые не требуют отрицательных значений, а значит, место под знак можно включить в представление неотрицательного числа, удвоив количество различных неотрицательных значений. Как результат, в современных компьютерах используются как типы со знаком или знаковые типы, так и типы без знака или беззнаковые типы.

В итоге можно составить таблицу наиболее используемых целочисленных типов данных:

Общее название Название в Pascal Название в C++ Описание Диапазон значений
unsigned byte byte unsigned char беззнаковый 8 бит 0..255
signed byte shortint char знаковый 8 бит -128..127
unsigned word word unsigned short беззнаковый 16 бит 0..65535
signed word smallint short знаковый 16 бит -32768..32767
unsigned double word cardinal unsigned int беззнаковый 32 бита 0..232-1
signed double word integer int знаковый 32 бита -231..231-1
unsigned quad word uint64 unsigned long long
unsigned __int64_t (VC++)
беззнаковый 64 бита 0..264-1
signed quad word int64 long long
__int64_t (VC++)
знаковый 64 бита -263..263-1

Понравилась статья? Поделить с друзьями:
  • Download the converter of pdf to word
  • Double word in english
  • Download templates for word free download
  • Double text in word
  • Download template for word free download