Skip navigation

Szorzás

Áttekintés

A szorzás esetében megkülönböztetjük az előjeles, és előjel nélküli számok szorzását. Ezen két műveletre külön-külön utasítás is van a processzorban.

Előjel nélküli szorzás

32 bites módban az egész értékek összeszorzása elvégezhető, mint egy 32, 16 vagy 8 bites művelet.

MUL: 32 bites módban a MUL (unsigned MULtiply - előjelnélküli szorzás) utasításnak három verziója van: az első verzió egy 8 bites operandust szoroz össze az AL regiszterrel. A második verzió egy 16 bites operandust szoroz össze az AX regiszterrel. A harmadik verzió egy 32 bites operandust szoroz össze az EAX regiszterrel. A szorzó és a szorzandó méretének mindig meg kell egyeznie és a szorzat mindig ennek a méretnek a kétszerese. A három formátum elfogad regisztert és memória címet is operandusként, viszont sosem közvetlen operandust (konstanst):

            MUL reg/mem8

     MUL reg/mem16

     MUL reg/mem32

 

A MUL utasításnak tehát egy operandusa van, ami a szorzó. Az alábbi táblázat mutatja be az alapértelmezett szorzandót és a szorzatot, attól függően, hogy mekkora mérető szorzót adtunk meg:

Szorzandó Szorzó Szorzat
AL reg/mem8 AX
AX reg/mem16 DX:AX
EAX reg/mem32 EDX:EAX 


A táblázatban leírtak értelmezése: ha az AL regiszter tartalmát megszorozzuk egy 8 bites operandussal, akkor az eredmény az AX regiszterbe kerül. Az AX megszorozva egy 16 bites operandussal, az eredmény a DX és AX regiszterekbe kerül, ami azt jelenti, hogy a szorzat felső 16 bitje a DX regiszterbe, míg az alsó 16 bit az AX regiszterbe kerül tárolásra. Ugyanezen az elven működik az EAX regiszter megszorzása egy 32 bites operandussal, mely során az eredmény az EDX és EAX regiszterekbe kerül. Mivel a cél operandus mérete kétszer akkora, mint a szorzandó és a szorzó mérete, ezért túlcsordulás nem fordulhat elő. A Carry flag 1 értéke jelzi, ha történt átvitel 8 bites szorzás esetén az AH-ba, 16 bites szorzás esetén az DX-be, illetve 32 bites szorzás esetén az EDX-be.

Előjel nélküli szorzás példák

     MOV AL, 150d   ; AL = 96h

     MOV BL, 10d    ; BL = 0Ah

     MUL BL         ; AX = AL * BL = 96h * 0Ah = 05DCh


     MOV AX, 8000d  ; AX = 1F40h 

     MOV BX, 5000d  ; BX = 1388h

     MUL BX         ; DX:AX = AX * BX = 1F40h * 1388h = 0262 5A00h


     MOV EAX, 1000000d   ; EAX = 000F 4240h

     MOV EBX, 5000000d   ; EBX = 004C 4B40h

     MUL EBX        ; EDX:EAX = EAX * EBX = 0000 048C 2739 5000h


     MUL WORD PTR [SI]   ; DX:AX = AX * (SI helyen a memóriában

                          ; található szó)

     ; Kell a WORD PTR, mert a fordító nem tudja, hány bites 

     ; művelet! Természetesen a WORD helyett használhatunk BYTE,

     ; illetve DWORD típust is

Előjeles szorzás

IMUL: Előjeles szorzás. Működése hasonló a MUL utasításhoz, azzal a különbséggel, hogy az IMUL megőrzi a szorzat előjelét. Az x86-os utasítás halmaz három különböző formátumát támogatja az IMUL utasításnak: egy-, kettő-, illetve három operandusos verzió.

Az egy operandusú verzió használata megegyezik a MUL utasításéval:

Példa:

     MOV AL, -2d    ;    AL = 0FEh

     MOV CL, 3d     ;    CL = 03h

     IMUL CL        ;    AX = 0FFFAh

IMUL két operandussal (80286-tól): az első operandus egy regiszter (16 vagy 32 bites), a második operandus lehet regiszter, memóriahivatkozás vagy közvetlen érték (konstans), az elsővel egyező bitszélességű. Az eredmény az első operandusban keletkezik. Nagyon fontos, hogy itt nincs bitszélesség kiterjesztés, tehát nincs átvitel 16 bites szorzás esetén DX-be, illetve 32 bites szorzás esetén EDX-be. A C és O flag mutatják, ha van elveszett átvitel.

Példa:

     MOV AX, -2d    ;    AX = 0FFFEh

     MOV BX, 5d     ;    BX = 5h

     IMUL AX, BX    ;    AX = AX * BX = 0FFF6h

     IMUL AX, 3h    ;    AX = AX * 3h = 0FFE2h


     ADAT1     DD   912, 920, 928, 936, 944 ; adatszegmens tartalma


     MOV EDX, offset ADAT1

     IMUL AX, [EDX] ;    AX = AX * [EDX] = 9520h

                    ;    (nincs átvitel, elvesszük az előjelet!)

                    ;    átvitellel, helyesen FFFF 9520h lenne

 

IMUL három operandussal (80386-tól): az első operandus egy regiszter (16 vagy 32 bites), a második operandus lehet regiszter vagy memóriahivatkozás, a harmadik operandus egy közvetlen érték (konstans). A második és a harmadik operandus kerül összeszorzásra és az eredmény az első operandusban keletkezik. A két operandusos verzióhoz hasonlóan itt sincs bitszélesség kiterjesztés, viszont az O és C flag jelzik az elveszett átvitelt.

Példa:

     MOV BX, 3d          ;    BX = 3h

     IMUL AX, BX, 6d     ;    AX = BX * 6h = 3h * 6h = 0Ch