Computer Security

#13 산술 및 논리 연산 명령어1 본문

컴퓨터구조&어셈블리어

#13 산술 및 논리 연산 명령어1

쿠리 Kuri 2022. 5. 27. 18:30

음수와 양수

-컴퓨터에서 정수 데이터는 부호가 있는(signed) 경우부호가 없는(unsigned) 경우로 분류 된다.

-부호가 없는 경우 모든 비트가 정수의 데이터 비트로 이용되지만, 부호가 있는 경우 최상위 비트(MSB)가 부호 비트로 이용된다.

-음수를 표현하기 위해 2의 보수법을 이용하며, 부호의 유무와 상관없이 덧셈과 뺄셈의 결과로 나오는 비트 데이터는

동일하다.

-ADD와 SUB명령어는 데이터의 부호 유무를 구별하지 않고 단순히 비트들을 더하고 뺀다.

ex) 다음과 같이 1바이트 정수 덧셈을 하는 경우 249와 2를 더하는 경우와 -7과2를 더하는 경우 모두 결과값이

     11111011로 비트 필드가 서로 같다.

 

이진수                부호 없는 십진수      부호 있는 십진수

1111  1001                     249                    -7

0000  0010                   +   2                +   2

ㅡㅡㅡㅡㅡ                ㅡㅡㅡㅡㅡ           ㅡㅡㅡㅡㅡ

1111  1011                    251                     -5

 

 

산술 캐리와 오버플로우

-플래그 레지스터에는 산술 연산의 결과를 반영하는 플래그 비트들이 존재한다.

-그중 제로(Zero)나 캐리(Carry), 오버플로우(Overflow)는 덧셈이나 뺄셈에서 발생할 수 있는 상태 값들이다.

 

캐리: '자리 올림'이라고도 한다. 주어진 이진수의 최상위 비트(MSB)의 상위 비트로 자리 올림이 발생할 경우 캐리 플래그(CF)가 1로 세트(set)된다.

 

ex)     이진수                    위 결과가 부호 없는 십진수 일때는 252+5  = 1이 나온다.

      1111   1100                원래는 257이 나와야 하지만 256까지 이므로 결과값은 1 로 보인다.  

   + 0000   0101               하지만, 캐리플로우에 1이 올라간것. 산술연산상으론 틀리지만, 내부는 잘 작동

ㅡㅡㅡㅡㅡㅡㅡㅡㅡ          반면, 부호 있는 십진수는 -4 +5 =1 이므로 산술연산상으로 틀리지 않다.

(1)  0000   0001

 

 

오버플로우

-수의 표현 범위를 벗어나면서 발생하는 연산 결과상의 오류이다.

-오버플로우가 발생하면 오버플로우 플래그인 OF가 1로 세트된다. 

ex) 8비트 부호있는 정수인 121에 양수 11을 더하면 127을 넘어가기 때문에(-128~127까지표현가능) OF는 1이 되고, 결과값은 -124가 된다.

-캐리는 부호없는 수가 표현 범위를 벗어나는 경우에 해당하지만, 자리올림수가 CF에 보존되고, 연산 오류를 의미하지 않는다.

 

ex)  이진수                  부호 없는 십진수          부호 있는 십진수       오버플로우(OF) =1

     0111  1001                   121                              121               캐리(CF) = 0

  + 0000  1011                +  11                             + 11

ㅡㅡㅡㅡㅡㅡㅡㅡ             ㅡㅡㅡㅡㅡ                     ㅡㅡㅡㅡㅡ

    1000  0100                    132                             -124

 

 

오버플로우와 캐리 발생 기준

-8비트 부호 있는 정수(0ㅣ1ㅣ2ㅣ3ㅣ4ㅣ5ㅣ6ㅣ7ㅣCF)를 기준으로 한다 할때, 비트 6에서 7로 발생하는 캐리를C1 ,  비트 7에서 그 위로 발생하는 캐리를 C2라 하자. 

C1과 C2가 다를 경우 오버플로우가 발생한다.

 

 

데이터 크기 확장

-산술 연산 과정에서 캐리나 오버플로우 등의 문제가 발생할 수 있기 때문에 데이터 표현 범위를 고려하여 적절한 크기의 데이터 유형을 선택해야 한다.

-x86은 데이터 크기 확장(ex.바이트->워드) 를 위한 여러가지 명령어들을 제공한다

-CBW: 바이트를 워드로 변환

-CDQ: 이중워드를 사중워드로 변환

-CWD: 워드를 이중워드로 변환(AX와 DX)

-CWDE:워드를 확장 이중워드로 변환(AX와 EAX)

 

 

덧셈과 뺄셈

-x86에서 덧셈과 뺄셈 명령어는 각각 ADD 와 SUB 로 부호의 유무와 관계 없이 이진수 데이터 사이의 덧셈과 뺄셈을 수행한다.

-일반적으로 opcode와 두 개의 피연산자로 이루어져있다.

 

 ADD,SUB             reg , reg

                         mem, reg

                         reg, mem

                         reg, imm

                         mem, imm

 

ex)   ADD op1, op2   -->   op1=op1+op2

 

 

상태 플래그와 플래그 레지스터

-CPU에는 프로세서의 상태를 나타내거나 프로세서를 제어하기 위해 각종 플래그 비트들을 유지하며, 이는 상태 레지스터(Status Register) 또는 플래그 레지스터(Flag Register)에 저장된다.

-산술 연산이나 논리 연산 명령어를 실행하면 연산 결과에 따라 캐리(CF), 제로(ZF), 오버플로우(OF) 등의 플래그 비트들이 결정된다.

-이런 상태 플래그들은 분기 명령어에서 특정 조건을 검사하여 프로그램의 실행 흐름을 제어할 때 이용되기도 한다.

 

 

보조캐리(하프캐리) = 4비트에서 자리올림 발생할 때

Flag  l오버플로우  방향  인터럽트  부호  제로(0)  보조 캐리    패리티  캐리 

ON   l   OV          DN      EI         NG      ZR         AC          PE       CY

OFF  l   NV          UP       DI        PL       NZ         NA         PO       NC

 

 

 

캐리를 포함한 덧셈과 뺄셈

-복수 개의 워드로 이루어진 큰 정수 간의 덧셈에는 상위 워드에 자리 올림, 즉 캐리를 반영할 필요가 있다.

-뺄셈의 경우도 마찬가지다.  x86은 캐리 비트를 포함하는 덧셈과 뺄셈 명령어인 ADC(Add with Carry)와 SBB(Subtract with Borrow)를 제공한다.

-플래그 : AF, CF, OF, PF, SF, ZF 에 영향을 미친다.

ex)ADC와 SBB 명령어의 일반적 형식 

          ADC/SBB    reg , reg

                         mem, reg

                         reg, mem

                         reg, imm

                         mem, imm

 

-->  ADC  op1, op2    :  op1 =op1+CF+op2

-->  SBB   op1, op2    :  op1 =op1-CF-op2

 

 

곱셈과 나눗셈

-x86에서 곱셈과 나눗셈 연산은 부호가 있는 경우와 부호가 없는 경우로 나뉜다.

-부호가 없는 경우에는 필드의 모든 비트들이 데이터 비트로사용되고, 부호가 있는 경우에는 최상위 비트가 부호비트(sign bit)로 사용되고 나머지 비트들이 데이터 비트로 사용된다.

-x86에서 곱셈과 나눗셈은 덧셈, 뺄셈과는 다르게 곱해지는 수인 피승수(multiplicand)과 나눠지는 수인 피제수(dividend)가, 곱의 결과와 나눗셈의 결과가 (E)AX와 (E)DX 레지스터에 저장되도록 고정되어있다.

-대신에 곱하는 수인 승수(multiplier)와 나누는 수인 제수(divisor)는 피승수와 피제수의 크기에 맞는 레지스터나 메모리 데이터를 지정할 수 있다.

 

ex)   op1 = op1 X op2  ( op1: 피승수, op2: 승수)

       op1 = op1 / op2  ( op1:피제수, op2: 제수)

 

 

곱셈

-x86은 부호 없는 곱셈 명령어인 MUL(Multiply)과 부호 있는 곱셈 명령어인 IMUL(Integer Multiply)를 제공한다.

-승수와 피승수의 크기는 서로 같아야 하며, 곱해진 결과를 저장하기 위해서는 곱해지는 두 수의 두 배 크기를 갖는 공간이 필요하다.(ex. 바이트 정수와 바이트 정수를 곱한 결과를 저장하려면 워드 크기의 공간이 필요하다.)

-피연산자로 승수(multiplier) 하나만을 받는다.

-피승수는 AX로 고정되어있다. 

-연산 결과는 AX와 DX에 저장된다.

플래그: CF, OF, (AF, PF, SF, ZF에는 영향을 미치지 않는다.)

 

일반적인 형식

         MUL/IMUL  reg

         MUL/IMUL  mem

 

-곱셈의 결과는 두 배의 공간을 요구하므로 8비트 곱셈을 하면 그 결과가 16비트 레지스터 AX에 저장되고, 16비트 곱셈을 하면 상위 16비트는 DX, 하위 16비트는 AX에 저장된다.

-80386 이상의 프로세서에서 32비트 곱셈의 결과는 상위 32비트가 EDX, 하위 32비트가 EAX에 저장된다.

 

나중가서는 IMUL  reg, imm(80286+) 처럼 레지스터를 정할 수도 있게 되었다.

 

 

나눗셈

-x86은 부호 없는 정수의 나눗셈 DIV(Divide)와 부호 있는 정수의 나눗셈 IDIV(Integer Divide)를 제공한다.

-나눗셈 연산의 경우 나눠지는 수인 피제수(dividend)의 데이터 크기는 나누는 수인 제수(divisor), 몫, 나머지의 두 배가 되어야 한다.

ex) 16비트 레지스터 AX에 있는 수에 나눗셈 연산을 적용하려면, 그 피연산자가 되는 제수는 8비트가 되어야 하며,

나눗셈의 몫은 AL ,  나머지는 AH에 저장된다.

 

플래그: AF, CF, OF, PF, SF, ZF

-피연산자로 피제수 하나만을 받고 있다.

-피연산자는 레지스터이거나 메모리가 되어야 한다.

-곱셈 명령어와 마찬가지로 나눗셈 명령어도 AX와 DX 레지스터를 사용하낟.

 

일반적인 형식

             DIV / IDIV   reg

             DIV / IDIV   mem

 

Comments