기본 어셈블리 언어 구성 요소 및 명령 구조. 데이터 형식 및 어셈블리 언어 명령어 구조. 주제 "시스템 프로그래밍"

소개.

원래 프로그램이 작성된 언어를 호출합니다. 입력언어 및 프로세서에서 실행하기 위해 번역되는 언어 - 주말언어. 입력 언어를 출력 언어로 변환하는 프로세스를 호출합니다. 방송.프로세서는 프로그래밍에 사용되지 않는 이진 기계어로 프로그램을 실행할 수 있으므로 모든 소스 프로그램의 번역이 필요합니다. 모두 다 아는 두 가지 방법번역: 편집 및 해석.

~에 편집소스 프로그램은 먼저 대상 언어의 동등한 프로그램으로 완전히 번역됩니다. 물체프로그램을 실행한 후 실행합니다. 이 과정은 특별한 방법을 사용하여 수행됩니다. 프로그램들,~라고 불리는 컴파일러.입력 언어가 이진 코드의 기계(출력) 언어의 상징적 표현인 컴파일러를 호출합니다. 어셈블러.

~에 해석소스 프로그램 텍스트의 각 라인이 구문 분석(해석)되고 여기에 지정된 명령이 즉시 실행됩니다. 이 방법의 구현은 다음과 같습니다. 통역 프로그램.해석에는 시간이 오래 걸립니다. 효율성을 높이기 위해 각 라인을 처리하는 대신 인터프리터가 모든 라인을 미리 변환합니다. 명령문자열을 문자로(

). 생성된 기호 시퀀스는 원래 프로그램에 할당된 기능을 수행하는 데 사용됩니다.

아래에서 설명하는 어셈블리 언어는 컴파일을 사용하여 구현됩니다.

언어의 특징.

어셈블러의 주요 기능:

● 이진 코드 대신 언어는 기호 이름을 사용합니다. 기억술.예를 들어 추가 명령(

) 니모닉 사용

빼기(

곱셈 (

디비전(

등. 기호 이름은 메모리 셀의 주소를 지정하는 데에도 사용됩니다. 어셈블리 언어로 프로그래밍하려면 이진 코드와 주소 대신 어셈블러가 이진 코드로 변환하는 기호 이름만 알면 됩니다.

각 진술은 해당 하나의 기계 명령(코드) 즉, 어셈블리 언어 프로그램에서 기계 명령어와 연산자 사이에 일대일 대응이 있습니다.

● 언어는 접근을 제공합니다 모든 객체에그리고 팀. 고급 언어에는 이러한 기능이 없습니다. 예를 들어 어셈블리 언어를 사용하면 플래그 레지스터 비트를 확인할 수 있고 고급 언어(예:

)에는 이 기능이 없습니다. 시스템 프로그래밍용 언어(예: C)는 종종 중간 위치를 차지합니다. 접근성 측면에서 어셈블리 언어에 가깝지만 고급 언어의 구문을 가지고 있습니다.

● 어셈블리 언어 보편적인 언어가 아닙니다.각각의 특정 마이크로프로세서 그룹에는 고유한 어셈블러가 있습니다. 고급 언어에는 이러한 단점이 없습니다.

고급 언어와 달리 어셈블리 언어 프로그램을 작성하고 디버깅하는 데는 많은 시간이 걸립니다. 그럼에도 불구하고 어셈블리 언어는 폭넓은 사용다음과 같은 상황으로 인해:

● 어셈블리 언어로 작성된 프로그램은 고급 언어로 작성된 프로그램보다 훨씬 작고 빠릅니다. 일부 응용 프로그램의 경우 이러한 표시기가 주요 역할을 합니다. 예를 들어 많은 시스템 프로그램(컴파일러 포함), 신용 카드 프로그램, 휴대폰, 장치 드라이버 등;

● 일부 절차가 필요합니다. 전체 권한일반적으로 고급 언어에서는 불가능합니다. 이 사례에는 운영 체제의 인터럽트 및 인터럽트 핸들러와 실시간 임베디드 시스템의 장치 컨트롤러가 포함됩니다.

대부분의 프로그램에서 전체 코드의 작은 비율만이 프로그램 실행 시간의 많은 부분을 차지합니다. 일반적으로 프로그램의 1%가 실행 시간의 50%를 담당하고 프로그램의 10%가 실행 시간의 90%를 담당합니다. 따라서 실제 상황에서 특정 프로그램을 작성하기 위해서는 어셈블러와 고급 언어 중 하나를 모두 사용한다.

어셈블리 언어의 연산자 형식.

어셈블리 언어 프로그램은 명령(명령문, 문장) 목록으로, 각 명령은 별도의 줄을 차지하고 레이블 필드, 작업 필드, 피연산자 필드 및 주석 필드의 네 가지 필드를 포함합니다. 각 필드에는 별도의 열이 있습니다.

레이블 필드.

열 1은 레이블 필드에 할당됩니다. 레이블은 기호 이름 또는 식별자입니다. 구애메모리. 다음을 수행하려면 필요합니다.

● 명령에 대한 조건부 또는 무조건 전환을 수행합니다.

● 데이터가 저장된 장소에 액세스하십시오.

이러한 진술에는 레이블이 지정됩니다. 명칭을 지정하기 위하여 영문의 (대문자)문자와 숫자를 사용한다. 이름은 문자로 시작하고 콜론으로 끝나야 합니다. 콜론 레이블은 별도의 줄에 작성할 수 있으며 opcode는 열 2의 다음 줄에 작성할 수 있으므로 컴파일러 작업이 단순화됩니다. 콜론이 없으면 레이블과 opcode가 별도의 줄에 있는 경우 구분할 수 없습니다.

어셈블리 언어의 일부 버전에서 콜론은 데이터 레이블이 아닌 명령어 레이블 뒤에만 배치되며 레이블 길이는 6자 또는 8자로 제한될 수 있습니다.

레이블 필드는 명령 주소와 연결되어 있으므로 레이블 필드에 동일한 이름이 포함되어서는 안 됩니다. 프로그램 실행 중에 메모리에서 명령이나 데이터를 호출할 필요가 없으면 레이블 필드가 비어 있습니다.

트랜잭션 코드 필드.

이 필드에는 mnemonic 또는 pseudo-command 명령이 포함됩니다(아래 참조). 명령 니모닉 코드는 언어 설계자가 선택합니다. 어셈블리 언어에서

메모리에서 레지스터를 로드하기 위해 선택된 니모닉

), 레지스터의 내용을 메모리에 저장 - 니모닉

). 어셈블리 언어에서

두 작업에 각각 동일한 이름을 사용할 수 있습니다.

니모닉 이름의 선택이 임의적일 수 있는 경우 두 개의 기계 명령어를 사용해야 하는 이유는 프로세서 아키텍처 때문입니다.

레지스터 니모닉도 어셈블러 버전에 따라 다릅니다(표 5.2.1).

피연산자 필드.

여기 위치 추가 정보작업을 수행하는 데 필요합니다. 점프 명령의 피연산자 필드에는 점프하려는 주소와 기계 명령의 피연산자 인 주소 및 레지스터가 표시됩니다. 예를 들어 8비트 프로세서에 사용할 수 있는 피연산자는 다음과 같습니다.

● 숫자 데이터,

다른 숫자 체계로 표시됩니다. 사용된 숫자 체계를 나타내기 위해 상수 뒤에 라틴 문자 중 하나가 옵니다: B,

따라서 2진수, 8진수, 16진수, 10진수 시스템(

기록되지 않을 수 있습니다). 16진수의 첫 자리가 A, B, C일 경우,

그런 다음 중요하지 않은 0(영)이 앞에 추가됩니다.

● 마이크로프로세서 내부 레지스터 및 메모리 셀의 코드

M(정보의 출처 또는 수신자) 문자 A, B, C,

M 또는 숫자 체계의 주소(예: 10V - 레지스터 주소

바이너리 시스템에서);

● 식별자,

등록된 항공기 쌍의 경우,

첫 글자 B

시간; 한 쌍의 누산기와 기능 레지스터의 경우 -

; 프로그램 카운터 -

; 스택 포인터의 경우 -

● 조건부에서 피연산자의 주소 또는 다음 명령을 나타내는 레이블

(조건이 충족되었을 때) 그리고 무조건 전환.예를 들어 명령의 피연산자 M1

레이블 필드의 주소가 식별자 M1로 표시되는 명령으로 무조건 전환해야 함을 의미합니다.

● 표현,

산술 및 논리 연산자를 사용하여 위에서 설명한 데이터를 연결하여 구축됩니다. 데이터 공간이 예약되는 방식은 언어 버전에 따라 다릅니다. 어셈블리 언어 개발자

단어 정의), 나중에 도입됨 대체 옵션.

처음부터 프로세서용 언어였습니다.

언어 버전에서

사용된

상수를 정의합니다).

프로세서는 길이가 다른 피연산자를 처리합니다. 이를 정의하기 위해 어셈블러 개발자는 다음과 같은 다양한 결정을 내렸습니다.

길이가 다른 II 레지스터는 이름이 다릅니다. EAX - 32비트 피연산자 배치(유형

); AX - 16비트용(유형

및 AN - 8비트의 경우(유형

● 프로세서용

접미사가 각 opcode에 추가됩니다. 접미사

유형

; 유형의 접미사 ".B"

길이가 다른 피연산자의 경우, 예를 들어 바이트, 하프워드(

) 및 64비트 레지스터의 워드는 opcode를 사용합니다.

각기.

댓글 필드.

이 필드는 프로그램의 작업에 대한 설명을 제공합니다. 댓글은 프로그램 운영에 영향을 미치지 않으며 개인을 위한 것입니다. 이러한 주석이 없으면 숙련된 프로그래머도 완전히 이해할 수 없는 프로그램을 수정하는 데 필요할 수 있습니다. 주석은 문자로 시작하며 프로그램을 설명하고 문서화하는 데 사용됩니다. 주석의 시작 문자는 다음과 같습니다.

● 회사 프로세서용 언어의 세미콜론(;)

느낌표(!) 언어로

주석용으로 예약된 각 줄 앞에는 시작 문자가 있습니다.

의사 명령(지시문).

어셈블리 언어에서 두 가지 주요 유형의 명령을 구분할 수 있습니다.

기초적인프로세서의 기계 코드에 해당하는 명령어. 이 명령은 프로그램에서 제공하는 모든 처리를 수행합니다.

의사 명령또는 지시,프로그램을 코드 조합 언어로 번역하는 프로세스를 제공하도록 설계되었습니다. 예를 들어 표에서. 5.2.2는 as-assembler의 의사 명령을 보여줍니다.

가족을 위해

.

프로그래밍할 때 알고리즘에 따라 동일한 명령 체인을 여러 번 반복해야 하는 상황이 있습니다. 이 상황에서 벗어나려면 다음을 수행할 수 있습니다.

● 발생할 때마다 원하는 명령 시퀀스를 작성합니다. 이 접근 방식은 프로그램의 양을 증가시킵니다.

● 이 시퀀스를 프로시저(서브루틴)로 정리하고 필요에 따라 호출합니다. 이러한 종료에는 단점이 있습니다. 짧고 자주 사용되는 순서로 특수 프로시저 호출 명령과 반환 명령을 실행해야 할 때마다 프로그램 속도가 크게 저하될 수 있습니다.

가장 간단하고 효과적인 방법일련의 명령을 반복해서 사용하는 것입니다. 매크로,프로그램에서 자주 발생하는 명령 그룹을 다시 번역하도록 설계된 의사 명령으로 생각할 수 있습니다.

매크로 또는 매크로 명령은 매크로 정의, 매크로 반전 및 매크로 확장의 세 가지 측면으로 특징지어집니다.

매크로 정의

이것은 프로그램 텍스트에서 참조로 사용되는 반복적으로 반복되는 프로그램 명령 시퀀스에 대한 지정입니다.

매크로의 구조는 다음과 같습니다.

표현 목록; 매크로 정의

위의 매크로 정의 구조에는 세 부분이 있습니다.

● 헤더

이름을 포함하는 매크로

의사 명령

그리고 일련의 매개변수;

● 점선 매크로;

● 팀

눈금

매크로 정의.

매크로 매개변수 세트에는 선택한 명령어 그룹의 피연산자 필드에 지정된 모든 매개변수 목록이 포함되어 있습니다. 이러한 매개변수가 프로그램의 초기에 제공된 경우 매크로 정의 헤더에서 생략할 수 있습니다.

선택한 지침 그룹을 재조립하기 위해 이름으로 구성된 호출이 사용됩니다.

다른 값이 있는 매크로 및 매개변수 목록.

어셈블러는 컴파일 중에 매크로 정의를 발견하면 이를 매크로 정의 테이블에 저장합니다. 이름의 프로그램에 후속 출연 (

) 매크로의 경우 어셈블러는 이를 매크로 본문으로 바꿉니다.

매크로 이름을 opcode로 사용하는 것을 호출합니다. 매크로 반전(매크로 호출) 및 매크로 본문으로 대체- 매크로 확장.

프로그램이 일련의 문자(문자, 숫자, 공백, 구두점 및 새 줄로 이동하기 위한 캐리지 리턴)로 표시되는 경우 매크로 확장은 이 시퀀스의 일부 문자열을 다른 문자열로 바꾸는 것으로 구성됩니다.

매크로 확장은 프로그램 실행 중이 아니라 조립 프로세스 중에 발생합니다. 문자열을 조작하는 방법은 다음에 할당됩니다. 매크로 도구.

조립과정이 진행됩니다 두 번에 걸쳐:

● 첫 번째 패스에서는 모든 매크로 정의가 유지되고 매크로 호출이 확장됩니다. 이 경우 소스 프로그램을 읽고 모든 매크로 정의가 제거된 프로그램으로 변환되며 각 매크로 호출은 매크로 본문으로 대체됩니다.

● 두 번째 패스는 수신된 프로그램을 매크로 없이 처리합니다.

매개변수가 있는 매크로.

매개변수가 다른 값을 가질 수 있는 반복되는 명령 시퀀스로 작업하기 위해 매크로 정의가 제공됩니다.

● 함께 실제매크로 호출의 피연산자 필드에 배치되는 매개변수

● 함께 공식적인매개변수. 매크로 확장 중에 매크로 본문에 나타나는 각 공식 매개변수는 해당하는 실제 매개변수로 대체됩니다.

매개변수와 함께 매크로 사용.

프로그램 1은 두 개의 유사한 명령 시퀀스를 보여줍니다. 첫 번째 명령이 P와

그리고 두 번째

프로그램 2에는 두 개의 형식 매개변수 P1과 P2가 있는 매크로가 포함되어 있습니다. 매크로 확장 중에 매크로 본문 내부의 각 P1 문자는 첫 번째 실제 매개변수(P,

), 기호 P2는 두 번째 실제 매개변수(

) 프로그램 번호 1에서. 매크로 호출에서

프로그램 2는 다음과 같이 표시됩니다: P,

첫 번째 실제 매개변수,

두 번째 실제 매개변수입니다.

프로그램 1

프로그램 2

MOV EBX, Q MOV EAX, PL

MOV Q, EAX MOV EBX, P2

MOV P,EBX MOV P2,EAX

확장된 기능.

언어의 몇 가지 고급 기능을 고려하십시오.

조건 분기 명령과 점프할 레이블이 포함된 매크로를 두 번 이상 호출하면 레이블이 중복되어(레이블 중복 문제) 오류가 발생합니다. 따라서 각 호출에는 (프로그래머에 의해) 별도의 레이블이 매개변수로 지정됩니다. 언어로

레이블은 로컬로 선언됩니다(

) 고급 기능 덕분에 어셈블러는 매크로가 확장될 때마다 자동으로 다른 레이블을 생성합니다.

다른 매크로 안에 매크로를 정의할 수 있습니다. 이 고급 기능은 조건부 프로그램 연결과 결합할 때 매우 유용합니다. 고려하다

IF WORDSIZE GT 16 M2 매크로

매크로 M2는 명령문의 두 부분에서 모두 정의할 수 있습니다.

그러나 정의는 프로그램이 16비트 또는 32비트 프로세서에서 어셈블되는지 여부에 따라 다릅니다. M1이 호출되지 않으면 매크로 M2가 전혀 정의되지 않습니다.

또 다른 고급 기능은 매크로가 자신을 포함하여 다른 매크로를 호출할 수 있다는 것입니다. 재귀부르다. 후자의 경우 무한 루프를 피하기 위해 매크로는 확장할 때마다 변경되는 매개변수를 자신에게 전달해야 합니다. 확인하다이 매개변수를 사용하고 매개변수가 특정 값에 도달하면 재귀를 종료합니다.

어셈블러에서 매크로 사용에 대해.

매크로를 사용할 때 어셈블러는 다음 두 가지 기능을 수행할 수 있어야 합니다. 매크로 정의 저장그리고 매크로 호출을 확장합니다.

매크로 정의를 저장합니다.

모든 매크로 이름은 테이블에 저장됩니다. 각 이름에는 필요한 경우 호출할 수 있도록 해당 매크로에 대한 포인터가 수반됩니다. 일부 어셈블러에는 매크로 이름에 대한 별도의 테이블이 있고 다른 어셈블러에는 매크로 이름과 함께 모든 기계 명령 및 지시문이 있는 공통 테이블이 있습니다.

조립 중 매크로를 만났을 때 만들어진:

새 테이블 요소매크로 이름, 매개 변수 수 및 매크로 본문이 저장될 다른 매크로 정의 테이블에 대한 포인터;

● 목록 공식적인매개변수.

그런 다음 단순히 문자열인 매크로 본문을 읽고 매크로 정의 테이블에 저장합니다. 루프 본문에서 발생하는 형식 매개변수가 표시됩니다. 특수 문자.

매크로의 내부 표현

프로그램 2(p. 244)에 대한 위의 예에서 다음과 같습니다.

MOV EAX, MOV EBX, MOV MOV &

여기서 세미콜론은 캐리지 리턴 문자로 사용되고 앰퍼샌드 &는 공식 매개변수 문자로 사용됩니다.

매크로 전화번호 광고 확장.

어셈블리 중에 매크로 정의가 발견될 때마다 매크로 테이블에 저장됩니다. 매크로가 호출되면 어셈블러는 입력 장치에서 입력 데이터 읽기를 일시적으로 중단하고 저장된 매크로 본문 읽기를 시작합니다. 매크로 본문에서 추출된 형식 매개변수는 실제 매개변수로 대체되고 호출에 의해 제공됩니다. 매개변수 앞에 앰퍼샌드 &를 사용하면 어셈블러가 매개변수를 인식할 수 있습니다.

많은 버전의 어셈블러가 있지만 어셈블리 프로세스에는 공통 기능이 있으며 여러 면에서 유사합니다. 2 패스 어셈블러의 작업은 아래에서 고려됩니다.

두 패스 어셈블러.

이 프로그램은 여러 연산자로 구성됩니다. 따라서 조립 중에 다음 작업 순서를 사용할 수 있습니다.

● 기계어로 번역합니다.

● 수신된 기계 코드를 파일로 전송하고 목록의 해당 부분을 다른 파일로 전송합니다.

● 전체 프로그램이 방송될 때까지 위의 절차를 반복하십시오.

그러나 이 방법은 효율적이지 않습니다. 예를 들어 소위 문제 주요 링크.첫 번째 명령문이 프로그램 맨 끝에 있는 P 명령문으로 점프하는 경우 어셈블러는 이를 변환할 수 없습니다. 그는 먼저 연산자 P의 주소를 결정해야 하며 이를 위해서는 전체 프로그램을 읽어야 합니다. 원래 프로그램의 각 전체 읽기를 호출합니다. 통로.두 번의 패스를 사용하여 순방향 참조 문제를 해결하는 방법을 보여드리겠습니다.

첫 번째 패스에서 모으다모든 기호 정의(레이블 포함)를 테이블에 저장하고 두 번째 패스에서 각 연산자를 읽고 어셈블합니다. 이 방법은 비교적 간단하지만 원래 프로그램을 통한 두 번째 통과에는 추가 I/O 시간이 필요합니다.

● 첫 번째 패스에서 전환하다프로그램을 중간 형식으로 만들고 테이블에 저장하면 원래 프로그램이 아닌 테이블에 따라 두 번째 패스가 수행됩니다. 이 조립 방법은 두 번째 패스에서 I/O 작업이 수행되지 않기 때문에 시간을 절약합니다.

첫 번째 패스.

첫 번째 패스의 목적- 기호 테이블을 만듭니다. 위에서 언급한 것처럼 첫 번째 패스의 또 다른 목표는 모든 매크로 정의를 저장하고 표시되는 대로 호출을 확장하는 것입니다. 따라서 문자 정의와 매크로 확장이 모두 동일한 패스에서 발생합니다. 기호는 다음 중 하나일 수 있습니다. 상표,또는 의미,-you 지시문을 사용하여 특정 이름이 지정됩니다.

;값 - 버퍼 크기

명령 레이블 필드의 기호 이름에 의미를 부여함으로써 어셈블러는 본질적으로 프로그램 실행 중에 각 명령이 갖게 될 주소를 설정합니다. 이를 위해 조립 프로세스 중 어셈블러는 다음을 저장합니다. 명령 주소 카운터(

) 특수 변수로. 첫 번째 패스가 시작될 때 특수 변수의 값은 0으로 설정되고 각 명령이 처리된 후 해당 명령의 길이만큼 증가합니다. 예를 들어 표에서. 5.2.3은 명령 및 카운터 값의 길이를 나타내는 프로그램의 일부를 보여줍니다. 테이블은 첫 번째 패스 중에 생성됩니다. 기호 이름, 지시어그리고 작업 코드,필요한 경우 오자테이블. 리터럴은 어셈블러가 자동으로 메모리를 예약하는 상수입니다. 최신 프로세서에는 직접 주소가 있는 명령어가 포함되어 있으므로 해당 어셈블러는 리터럴을 지원하지 않습니다.

심볼 테이블

각 이름에 대해 하나의 요소를 포함합니다(표 5.2.4). 기호 테이블의 각 요소에는 이름 자체(또는 이에 대한 포인터), 숫자 값, 때로는 다음과 같은 일부 추가 정보가 포함됩니다.

● 심볼과 관련된 데이터 필드의 길이;

● 메모리 재매핑 비트(어셈블러가 의도한 것과 다른 주소에 프로그램이 로드되는 경우 심볼 값이 변경되는지 여부를 나타냄);

● 프로시저 외부에서 기호에 액세스할 수 있는지 여부에 대한 정보.

기호 이름은 레이블입니다. 연산자를 사용하여 지정할 수 있습니다(예:

지침 표.

이 표에는 프로그램을 조립할 때 발생하는 모든 지시문 또는 의사 명령이 나열되어 있습니다.

작업 코드 테이블.

각 opcode에 대해 테이블에는 별도의 열이 있습니다. opcode 지정, 피연산자 1, 피연산자 2, opcode의 16진수 값, 명령어 길이 및 명령어 유형(표 5.2.5). 연산 코드는 피연산자의 수와 종류에 따라 그룹으로 나뉩니다. 명령 유형은 그룹 번호를 결정하고 해당 그룹의 모든 명령을 처리하기 위해 호출되는 프로시저를 지정합니다.

두 번째 패스.

두 번째 패스의 목적- 개체 프로그램을 만들고 필요한 경우 어셈블리 프로토콜을 인쇄합니다. 서로 다른 시간에 어셈블된 프로시저를 하나의 실행 파일로 연결하기 위해 링커에 필요한 정보를 출력합니다.

두 번째 패스(첫 번째 패스에서와 같이)에서는 명령문이 포함된 라인을 차례로 읽고 처리합니다. 원래 연산자 및 16진수에서 파생된 출력 물체나중에 인쇄하기 위해 코드를 인쇄하거나 버퍼링할 수 있습니다. 명령 주소 카운터를 재설정한 후 명령이 호출됩니다. 다음 진술.

원래 프로그램에는 다음과 같은 오류가 있을 수 있습니다.

주어진 기호가 정의되지 않았거나 두 번 이상 정의되었습니다.

● opcode가 잘못된 이름(오타로 인해)으로 표시되거나 피연산자가 충분하지 않거나 피연산자가 너무 많습니다.

● 운영자 없음

일부 어셈블러는 정의되지 않은 기호를 감지하여 바꿀 수 있습니다. 그러나 대부분의 경우 오류가 있는 문이 발견되면 어셈블러는 화면에 오류 메시지를 표시하고 어셈블리 프로세스를 계속 시도합니다.

어셈블리 언어 전용 기사.

MIRZO ULUGBEK의 이름을 따서 명명된 우즈베키스탄 국립 대학교

컴퓨터 기술 학부

주제: EXE 파일의 시맨틱 구문 분석.

완전한:

타슈켄트 2003.

머리말.

어셈블리 언어 및 명령어 구조.

EXE 파일 구조(시맨틱 파싱).

COM 파일의 구조.

바이러스가 작동하고 확산되는 방식.

디스어셈블러.

프로그램들.

머리말

프로그래머의 직업은 놀랍고 독특합니다. 우리 시대에 과학과 삶은 최신 기술 없이는 상상할 수 없습니다. 인간 활동과 관련된 모든 것은 없이는 할 수 없습니다. 컴퓨터 과학. 그리고 이것은 높은 개발과 완성도에 기여합니다. 개인용 컴퓨터의 개발이 시작된 지 그리 오래되지 않았지만 이 기간 동안 소프트웨어 제품에 엄청난 조치가 취해졌고 오랫동안 이러한 제품이 널리 사용될 것입니다. 컴퓨터 관련 지식 분야와 관련 기술이 폭발적으로 증가했습니다. 상업적인 측면을 고려하지 않는다면, 이 분야의 직업 활동에는 낯선 사람이 없다고 말할 수 있습니다. 많은 사람들이 이익이나 수입이 아닌 열정으로 프로그램 개발에 참여하고 있습니다. 물론 이것은 프로그램의 품질에 영향을 미쳐서는 안되며, 이 비즈니스에서는 말하자면 품질 성능, 안정적인 작업 및 우리 시대의 모든 요구 사항을 충족하기 위한 경쟁과 요구가 있습니다. 여기에서 많은 수의 램프 세트를 대체하게 된 60 년대 마이크로 프로세서의 출현에 주목할 가치가 있습니다. 서로 매우 다른 몇 가지 종류의 마이크로프로세서가 있습니다. 이러한 마이크로프로세서는 비트 용량과 내장 시스템 명령 면에서 서로 다릅니다. 가장 일반적인 것은 Intel, IBM, Celeron, AMD 등입니다. 이러한 모든 프로세서는 인텔 프로세서의 고급 아키텍처와 관련이 있습니다. 마이크로컴퓨터의 확산은 두 가지 주요 이유로 어셈블리 언어에 대한 태도를 재고하게 했습니다. 첫째, 어셈블리 언어로 작성된 프로그램은 훨씬 적은 메모리와 런타임을 필요로 합니다. 둘째, 어셈블리 언어에 대한 지식과 그에 따른 기계 코드는 고급 언어로 작업할 때 거의 제공되지 않는 기계 아키텍처에 대한 이해를 제공합니다. 대부분의 소프트웨어 엔지니어는 프로그램을 작성하기 쉬운 Pascal, C 또는 Delphi와 같은 고급 언어로 개발하지만 가장 강력하고 효율적인 소프트웨어전체적으로 또는 부분적으로 어셈블리 언어로 작성되었습니다. 고급 언어는 특별한 것을 피하기 위해 설계되었습니다 기술적 기능들특정 컴퓨터. 그리고 어셈블리 언어는 프로세서의 특정 특성을 위해 설계되었습니다. 따라서 특정 컴퓨터용 어셈블리 언어 프로그램을 작성하려면 아키텍처를 알아야 합니다. 요즘은 메인화면으로 소프트웨어 제품 EXE 파일입니다. 고려하면 긍정적인 측면이를 통해 프로그램 작성자는 프로그램의 불가침성을 확신할 수 있습니다. 그러나 종종 이것은 사실과 거리가 멀다. 디스어셈블러도 있습니다. 디스어셈블러의 도움으로 인터럽트 및 프로그램 코드를 찾을 수 있습니다. 어셈블러에 정통한 사람이 프로그램 전체를 자신의 취향에 맞게 리메이크하는 것은 어렵지 않을 것입니다. 아마도 이것은 가장 불용성 문제인 바이러스에서 오는 곳일 것입니다. 사람들은 왜 바이러스를 작성합니까? 일부는 놀라움으로이 질문을하고 일부는 분노하지만 그럼에도 불구하고 피해를 입히는 관점이 아니라 시스템 프로그래밍에 대한 관심으로이 작업에 관심이있는 사람들이 여전히 있습니다. 바이러스 쓰기 다른 이유. 일부는 시스템 호출을 좋아하고 다른 일부는 어셈블러에 대한 지식을 향상시킵니다. 나는이 모든 것을 내 안에 설명하려고 노력할 것입니다 기말 보고서. 또한 EXE 파일의 구조뿐만 아니라 어셈블리 언어에 대해서도 설명합니다.

^ 조립 언어.

최초의 컴퓨터가 등장한 시점부터 현재까지 프로그래머들 사이에서 어셈블리 언어에 대한 아이디어의 변화를 따라가는 것은 흥미 롭습니다.

옛날 옛적에 어셈블러는 컴퓨터가 어떤 유용한 일을 하도록 만드는 것이 불가능하다는 것을 모르는 언어였습니다. 점차 상황이 바뀌었다. 컴퓨터와 더 편리한 통신 수단이 등장했습니다. 그러나 다른 언어와 달리 어셈블러는 죽지 않았고 원칙적으로도 이것을 할 수 없었습니다. 왜? 답을 찾기 위해 일반적으로 어셈블리 언어가 무엇인지 이해하려고 노력할 것입니다.

요컨대 어셈블리어는 기계어를 상징적으로 표현한 것입니다. 가장 낮은 하드웨어 수준에서 기계의 모든 프로세스는 기계어의 명령(명령)에 의해서만 구동됩니다. 이로부터 일반적인 이름에도 불구하고 각 유형의 컴퓨터에 대한 어셈블리 언어가 다르다는 것이 분명합니다. 이것은 또한 적용됩니다 모습어셈블러로 작성된 프로그램과 이 언어가 반영하는 아이디어.

어셈블러에 대한 지식 없이는 하드웨어 관련 문제(또는 프로그램 속도 향상과 같은 하드웨어 관련 문제)를 실제로 해결하는 것은 불가능합니다.

프로그래머나 다른 사용자는 가상 세계를 구축하기 위한 프로그램까지 모든 고급 도구를 사용할 수 있으며, 아마도 컴퓨터가 프로그램이 작성된 언어의 명령이 아니라 실제로 실행되고 있다고 의심하지 않을 수도 있습니다. 완전히 다른 언어인 기계어의 지루하고 지루한 명령 시퀀스의 형태로 변형된 표현입니다. 이제 그러한 사용자에게 비표준 문제가 있거나 무언가 잘못되었다고 상상해 봅시다. 예를 들어 그의 프로그램은 특이한 장치와 함께 작동하거나 컴퓨터 하드웨어 원리에 대한 지식이 필요한 다른 작업을 수행해야 합니다. 프로그래머가 아무리 똑똑하고 훌륭한 프로그램을 작성한 언어가 아무리 훌륭하더라도 어셈블러에 대한 지식 없이는 할 수 없습니다. 그리고 거의 모든 고급 언어 컴파일러가 어셈블러의 모듈과 모듈을 연결하는 수단을 포함하거나 어셈블러 프로그래밍 수준에 대한 액세스를 지원하는 것은 우연이 아닙니다.

물론 컴퓨터 마차의 시대는 이미 지나갔다. 속담처럼 광대함을 받아들일 수 없습니다. 그러나 진지한 컴퓨터 교육이 구축되는 일종의 공통점이 있습니다. 이것은 컴퓨터 작동 원리, 아키텍처 및 이 지식의 반영 및 구현으로서의 어셈블리 언어에 대한 지식입니다.

일반적인 최신 컴퓨터(i486 또는 Pentium 기반)는 다음 구성 요소로 구성됩니다(그림 1).

쌀. 1. 컴퓨터와 주변기기

쌀. 2. 개인용 컴퓨터의 블록도

그림(그림 1)에서 컴퓨터는 여러 물리적 장치로 구성되어 있으며 각 장치는 시스템 장치라고 하는 하나의 장치에 연결되어 있음을 알 수 있습니다. 논리적으로 보면 일종의 조정 장치 역할을 하는 것은 분명하다. 내부를 살펴보자 시스템 블록(모니터 내부에 들어 가려고 할 필요가 없습니다. 위험한 것 외에는 흥미로운 것이 없습니다.) 케이스를 열고 일부 보드, 블록, 연결 와이어를 봅니다. 기능적 목적을 이해하기 위해 일반적인 컴퓨터의 블록 다이어그램을 살펴보겠습니다(그림 2). 그것은 절대적인 정확성을 가장하지 않으며 현대 개인용 컴퓨터 요소의 목적, 상호 연결 및 일반적인 구성을 보여주는 것을 목표로 합니다.

그림의 다이어그램에 대해 논의해 봅시다. 2 다소 색다른 스타일.
미지의 것을 알도록 도와줄 수 있는 어떤 연관성을 찾는 것은 새로운 것을 만나는 인간의 본성입니다. 컴퓨터는 어떤 연관성을 불러일으킵니까? 예를 들어 나에게 컴퓨터는 종종 그 사람 자신과 연결됩니다. 왜?

자신의 깊은 곳 어딘가에서 컴퓨터를 만드는 사람은 자신과 비슷한 것을 만들고 있다고 생각했습니다. 컴퓨터에는 외부 세계의 정보 인식 기관이 있습니다. 이것은 키보드, 마우스, 자기 디스크 드라이브입니다. 무화과. 2 이 오르간은 시스템 버스의 오른쪽에 있습니다. 컴퓨터에는 수신된 정보를 "소화"하는 기관이 있습니다. CPU그리고 작업 기억. 그리고 마지막으로 컴퓨터에는 처리 결과를 제공하는 음성 기관이 있습니다. 이들은 또한 오른쪽에 있는 일부 장치입니다.

최신 컴퓨터, 물론 인간과는 거리가 멀다. 그들은 크지만 제한적인 무조건 반사 수준에서 외부 세계와 상호 작용하는 존재에 비유할 수 있습니다.
이 일련의 반사는 기계 명령 시스템을 형성합니다. 아무리 높은 수준의 컴퓨터와 통신하더라도 결국 모든 것은 지루하고 단조로운 일련의 기계 명령으로 귀결됩니다.
각 기계 명령은 이것 또는 저 무조건 반사를 흥분시키는 일종의 자극입니다. 이 자극에 대한 반응은 항상 모호하지 않으며 마이크로 프로그램의 형태로 마이크로 명령 블록에 "고정"되어 있습니다. 이 마이크로 프로그램은 기계 명령의 구현을 위한 조치를 구현하지만 이미 특정에 주어진 신호 수준에 있습니다. 논리컴퓨터, 따라서 컴퓨터의 다양한 하위 시스템을 제어합니다. 이것이 소위 마이크로 프로그램 제어의 원리입니다.

사람과의 비유를 계속하면서 우리는 컴퓨터가 제대로 먹기 위해 많은 운영 체제, 수백 가지 프로그래밍 언어에 대한 컴파일러 등이 발명되었지만 실제로는 모두 접시에 불과합니다. 음식(프로그램)은 위(컴퓨터)의 특정 규칙에 따라 배달됩니다. 컴퓨터의 위장만이 단조로운 음식을 좋아합니다. 엄격하게 구성된 0과 1의 시퀀스 형태로 구조화된 정보를 제공하고 그 조합이 기계 언어를 구성합니다.

따라서 겉으로는 다국어이기 때문에 컴퓨터는 기계 명령 언어라는 하나의 언어 만 이해합니다. 물론 컴퓨터와 의사 소통하고 작업하기 위해이 언어를 알 필요는 없지만 거의 모든 전문 프로그래머가 조만간 배울 필요성에 직면합니다. 다행스럽게도 프로그래머는 50 년대 초반부터 프로그래머가 어셈블리 언어라고하는 프로그래밍을 위해 기계 언어의 상징적 아날로그를 사용하기 시작했기 때문에 다양한 이진수 조합의 의미를 파악하려고 노력할 필요가 없습니다. 이 언어는 기계어의 모든 기능을 정확하게 반영합니다. 그렇기 때문에 고급 언어와 달리 컴퓨터 기종마다 어셈블리 언어가 다릅니다.

위에서 우리는 컴퓨터의 어셈블리 언어가 "네이티브"이기 때문에 가장 효율적인 프로그램은 그 안에서만 작성될 수 있다는 결론을 내릴 수 있습니다(자격을 갖춘 프로그래머가 작성한 경우). 여기에 하나의 작은 "그러나"가 있습니다. 이것은 많은 관심과 실제 경험이 필요한 매우 힘든 과정입니다. 따라서 실제로 어셈블러는 주로 다음을 제공해야 하는 프로그램을 작성합니다. 효율적인 작업하드웨어로. 때로는 실행 시간이나 메모리 소비 측면에서 프로그램의 중요한 부분이 어셈블러로 작성됩니다. 이후 서브루틴 형태로 만들어지고 고급 언어의 코드와 결합된다.

컴퓨터의 어떤 부분이 표시되고 이 언어로 프로그래밍할 수 있는지 알아낸 후에만 컴퓨터의 어셈블리 언어 학습을 시작하는 것이 이치에 맞습니다. 이것은 프로그래머가 사용할 수 있는 32개의 레지스터를 포함하는 마이크로프로세서 프로그램 모델의 일부인 소위 컴퓨터 프로그램 모델입니다.

이러한 레지스터는 두 개의 큰 그룹으로 나눌 수 있습니다.

^16개의 커스텀 레지스터;

16개의 시스템 레지스터.

어셈블리 언어 프로그램은 레지스터를 매우 많이 사용합니다. 대부분의 레지스터에는 특정한 기능적 목적이 있습니다.

이름에서 알 수 있듯이 사용자 레지스터는 프로그래머가 프로그램을 작성할 때 사용할 수 있기 때문에 호출됩니다. 이러한 레지스터에는 다음이 포함됩니다(그림 3).

프로그래머가 데이터와 주소를 저장하는 데 사용할 수 있는 8개의 32비트 레지스터(RON(범용 레지스터)라고도 함):

6개의 세그먼트 레지스터: cs, ds, ss, es, fs, gs;

상태 및 제어 레지스터:

플래그는 플래그/플래그를 등록합니다.

eip/ip 명령 포인터 레지스터.

쌀. 3. i486 및 Pentium 마이크로프로세서의 사용자 레지스터

많은 레지스터가 슬래시로 표시되는 이유는 무엇입니까? 아니요, 이들은 서로 다른 레지스터가 아니라 하나의 큰 32비트 레지스터의 일부입니다. 프로그램에서 별도의 개체로 사용할 수 있습니다. 이것은 i8086부터 시작하여 Intel의 더 젊은 16비트 마이크로프로세서 모델용으로 작성된 프로그램의 작동성을 보장하기 위해 수행되었습니다. i486 및 Pentium 마이크로프로세서에는 대부분 32비트 레지스터가 있습니다. 세그먼트 레지스터를 제외한 번호는 i8086과 동일하지만 치수가 더 커서 지정에 반영됩니다.
접두사 e(확장).

^ 범용 레지스터
이 그룹의 모든 레지스터는 "하위" 부분에 액세스할 수 있습니다(그림 3 참조). 이 그림을 보면 이러한 레지스터의 하위 16비트 및 8비트 부분만 자체 주소 지정에 사용할 수 있습니다. 이러한 레지스터의 상위 16비트는 독립 개체로 사용할 수 없습니다. 이는 위에서 언급한 바와 같이 Intel의 최신 16비트 마이크로프로세서 모델과의 호환성을 위해 수행됩니다.

범용 레지스터 그룹에 속하는 레지스터를 나열해 보겠습니다. 이러한 레지스터는 산술 논리 장치(ALU) 내부의 마이크로프로세서에 물리적으로 위치하므로 ALU 레지스터라고도 합니다.

eax/ax/ah/al (누산기 레지스터) - 누산기.
중간 데이터를 저장하는 데 사용됩니다. 일부 명령에서는 이 레지스터를 사용해야 합니다.

ebx/bx/bh/bl(기본 레지스터) - 기본 레지스터.
일부 개체의 기본 주소를 메모리에 저장하는 데 사용됩니다.

ecx/cx/ch/cl(카운트 레지스터) - 카운터 레지스터.
일부 반복 작업을 수행하는 명령에 사용됩니다. 그것의 사용은 종종 해당 명령의 알고리즘에 암시적이고 숨겨져 있습니다.
예를 들어 루프 구성 명령은 특정 주소에 있는 명령으로 제어를 이전하는 것 외에도 ecx/cx 레지스터의 값을 분석하고 1씩 감소시킵니다.

edx/dx/dh/dl (데이터 레지스터) - 데이터 레지스터.
eax/ax/ah/al 레지스터와 마찬가지로 중간 데이터를 저장합니다. 일부 명령은 이를 사용해야 합니다. 일부 명령의 경우 이는 암시적으로 발생합니다.

다음 두 레지스터는 각각 32, 16 또는 8비트 길이일 수 있는 요소 체인을 순차적으로 처리하는 작업인 체인 작업을 지원하는 데 사용됩니다.

esi/si(소스 인덱스 레지스터) - 소스 인덱스.
체인 작업의 이 레지스터에는 소스 체인에 있는 요소의 현재 주소가 포함됩니다.

edi/di(목적지 색인 레지스터) - 수신자(수신자)의 색인.
체인 작업의 이 레지스터에는 대상 체인의 현재 주소가 포함됩니다.

하드웨어 및 소프트웨어 수준의 마이크로 프로세서 아키텍처에서는 스택과 같은 데이터 구조가 지원됩니다. 마이크로프로세서 명령 시스템에서 스택으로 작업하기 위한 특수 명령이 있으며 마이크로프로세서 소프트웨어 모델에는 이를 위한 특수 레지스터가 있습니다.

esp/sp(스택 포인터 레지스터) - 스택 포인터 레지스터.
현재 스택 세그먼트의 스택 맨 위에 대한 포인터를 포함합니다.

ebp/bp(기본 포인터 레지스터) - 스택 프레임 기본 포인터 레지스터.
스택 내부의 데이터에 대한 임의 액세스를 구성하도록 설계되었습니다.

스택은 임의의 데이터를 임시로 저장하는 프로그램 영역입니다. 물론 데이터 세그먼트에 데이터를 저장할 수도 있지만, 이 경우 임시로 저장된 각 데이터에 대해 별도의 명명된 메모리 셀을 만들어야 하므로 프로그램의 크기와 사용되는 이름의 수가 증가합니다. 스택의 편리함은 해당 영역을 재사용하고 스택에 데이터를 저장하고 스택에서 가져오는 작업을 이름을 지정하지 않고 효율적인 푸시 및 팝 명령을 사용하여 수행한다는 것입니다.
예를 들어 스택은 전통적으로 서브루틴을 호출하기 전에 프로그램이 사용하는 레지스터의 내용을 저장하는 데 사용되며, 서브루틴은 "자체 목적을 위해" 프로세서 레지스터를 사용합니다. 레지스터의 원래 내용은 서브루틴에서 반환될 때 스택에서 유출됩니다. 또 다른 일반적인 기술은 스택을 통해 서브루틴에 필요한 매개변수를 전달하는 것입니다. 매개변수가 스택에 배치되는 순서를 알고 있는 서브루틴은 여기에서 매개변수를 가져와서 실행에 사용할 수 있습니다. 구별되는 특징스택은 그 안에 포함된 데이터의 일종의 샘플링 순서입니다. 언제든지 스택에서 최상위 요소만 사용할 수 있습니다. 스택에 로드된 마지막 요소. 스택에서 맨 위 요소를 팝하면 다음 요소를 사용할 수 있습니다. 스택의 요소는 스택의 맨 아래(즉, 최대 주소)부터 시작하여 연속적으로 감소하는 주소까지 스택에 할당된 메모리 영역에 위치합니다. 액세스 가능한 최상위 요소의 주소는 스택 포인터 레지스터 SP에 저장됩니다. 프로그램 메모리의 다른 영역과 마찬가지로 스택은 일부 세그먼트에 포함되거나 별도의 세그먼트를 형성해야 합니다. 두 경우 모두 해당 세그먼트의 세그먼트 주소는 세그먼트 스택 레지스터 SS에 배치됩니다. 따라서 한 쌍의 레지스터 SS:SP는 사용 가능한 스택 셀의 주소를 설명합니다. SS는 스택의 세그먼트 주소를 저장하고 SP는 스택에 저장된 마지막 데이터의 오프셋을 저장합니다(그림 4, a). 초기 상태에서 스택 포인터 SP는 스택의 맨 아래에 있고 스택에 포함되지 않은 셀을 가리킨다는 사실에 주목합시다.

그림 4. 스택 구성: a - 초기 상태, b - 하나의 요소를 로드한 후(이 예에서는 AX 레지스터의 내용), c - 두 번째 요소를 로드한 후(DS 레지스터의 내용), d - 하나를 언로드한 후 요소, e - 두 개의 요소를 언로드한 후 원래 상태로 돌아갑니다.

스택에 로드하는 작업은 특수한 푸시 스택 명령으로 수행됩니다. 이 명령어는 먼저 스택 포인터의 내용을 2만큼 감소시킨 다음 피연산자를 SP의 주소에 배치합니다. 예를 들어 스택에 있는 AX 레지스터의 내용을 일시적으로 저장하려면 다음 명령을 실행해야 합니다.

스택은 그림에 표시된 상태로 전환됩니다. 1.10, 나. 스택 포인터가 2바이트 위로(하위 주소 쪽으로) 이동되고 이 주소에 푸시 명령에 지정된 피연산자가 기록되는 것을 볼 수 있습니다. 예를 들어 다음 명령은 스택에 로드합니다.

스택을 그림에 표시된 상태로 이동합니다. 1.10, 다. 스택은 이제 스택 포인터 SP가 가리키는 맨 위 요소만 액세스되는 두 개의 요소를 보유합니다. 일정 시간이 지난 후 스택에 저장된 레지스터의 원래 내용을 복원해야 하는 경우 스택에서 pop 명령(pop)을 실행해야 합니다.

팝 DS
팝 도끼

스택은 얼마나 커야 합니까? 프로그램에서 얼마나 집중적으로 사용하느냐에 따라 다릅니다. 예를 들어 스택에 10,000바이트의 배열을 저장하려는 경우 스택은 최소한 그 크기여야 합니다. 어떤 경우에는 특히 인터럽트 명령 int 21h를 실행할 때 스택이 시스템에서 자동으로 사용된다는 점을 염두에 두어야 합니다. 이 명령으로 프로세서는 먼저 반환 주소를 스택에 푸시한 다음 DOS가 레지스터의 내용과 인터럽트된 프로그램과 관련된 기타 정보를 스택에 푸시합니다. 따라서 프로그램이 스택을 전혀 사용하지 않더라도 스택은 여전히 ​​프로그램에 존재해야 하며 크기는 적어도 수십 단어 이상이어야 합니다. 첫 번째 예에서 스택에 128개의 단어를 넣었는데, 이는 확실히 충분합니다.

^ 어셈블리 프로그램 구조

어셈블리 언어 프로그램은 메모리 세그먼트라고 하는 메모리 블록의 모음입니다. 프로그램은 이러한 블록 세그먼트 중 하나 이상으로 구성될 수 있습니다. 각 세그먼트에는 언어 문장 모음이 포함되어 있으며 각 문장은 별도의 프로그램 코드 줄을 차지합니다.

어셈블리 문에는 네 가지 유형이 있습니다.

기계 명령어의 상징적 대응물인 명령 또는 명령어. 번역 과정에서 어셈블리 명령어는 마이크로프로세서 명령어 세트의 해당 명령어로 변환됩니다.

매크로 명령 - 특정 방식으로 설계되고 번역 중에 다른 문장으로 대체되는 프로그램 텍스트의 문장

어셈블러 컴파일러에게 어떤 작업을 수행하도록 지시하는 지시문. 지시문에는 기계 표현에 상응하는 항목이 없습니다.

러시아 알파벳 문자를 포함하여 모든 문자를 포함하는 주석 행. 주석은 번역자에 의해 무시됩니다.

^ 어셈블리 언어 구문

프로그램을 구성하는 문장은 명령, 매크로, 지시문 또는 주석에 해당하는 구문 구조일 수 있습니다. 어셈블러 번역기가 이를 인식하려면 특정 구문 규칙에 따라 구성되어야 합니다. 이렇게 하려면 문법 규칙과 같은 언어 구문에 대한 공식적인 설명을 사용하는 것이 가장 좋습니다. 이러한 방식으로 프로그래밍 언어를 설명하는 가장 일반적인 방법은 구문 다이어그램과 확장된 Backus-Naur 형식입니다. 을 위한 실용구문 다이어그램이 더 편리합니다. 예를 들어 어셈블리 언어 문의 구문은 다음 그림에 표시된 구문 다이어그램을 사용하여 설명할 수 있습니다.

쌀. 5. 어셈블러 문장 형식

쌀. 6. 포맷 지시어

쌀. 7. 명령 및 매크로 형식

이 도면에서:

레이블 이름 - 값이 나타내는 프로그램 소스 코드 문장의 첫 번째 바이트 주소인 식별자.

이름 - 이 지시어를 동일한 이름의 다른 지시어와 구별하는 식별자입니다. 어셈블러가 특정 지시문을 처리한 결과 이 ​​이름에 특정 특성을 할당할 수 있습니다.

연산 코드(COP) 및 지시어는 해당 기계 명령어, 매크로 명령어 또는 번역기 지시어의 니모닉 지정입니다.

피연산자 - 작업이 수행되는 개체를 나타내는 명령, 매크로 또는 어셈블러 지시문의 일부입니다. 어셈블러 피연산자는 연산 부호와 일부 예약어를 사용하는 숫자 및 텍스트 상수, 변수 레이블 및 식별자가 있는 식으로 설명됩니다.

^ 구문 다이어그램을 사용하는 방법? 매우 간단합니다. 다이어그램의 입력(왼쪽)에서 출력(오른쪽)까지의 경로를 찾아서 따라가기만 하면 됩니다. 그러한 경로가 존재하면 문장이나 구성이 구문적으로 올바른 것입니다. 그러한 경로가 없으면 컴파일러는 이 생성을 허용하지 않습니다. 구문 다이어그램으로 작업할 때 화살표로 표시된 우회 방향에 주의하십시오. 경로 중에 오른쪽에서 왼쪽으로 따라갈 수 있는 경로가 있을 수 있기 때문입니다. 실제로 구문 다이어그램은 프로그램의 입력 문장을 구문 분석할 때 번역기의 논리를 반영합니다.

프로그램 텍스트를 작성할 때 허용되는 문자는 다음과 같습니다.

모두 편지: AZ, AZ. 이 경우 대문자와 소문자는 동일한 것으로 간주됩니다.

0에서 9까지의 숫자;

기호?, @, $, _, &;

구분자, . ()< > { } + / * % ! " " ? \ = # ^.

어셈블러 문장은 구문적으로 분리할 수 없는 유효한 언어 기호 시퀀스인 어휘소로 구성되며 번역자에게 의미가 있습니다.

토큰은 다음과 같습니다.

식별자는 opcode, 변수 이름 및 레이블 이름과 같은 프로그램 개체를 지정하는 데 사용되는 유효한 문자 시퀀스입니다. 식별자 작성 규칙은 다음과 같습니다. 식별자는 하나 이상의 문자로 구성될 수 있습니다. 문자로는 라틴 알파벳 문자, 숫자 및 일부 특수 문자(_, ?, $, @)를 사용할 수 있습니다. 식별자는 숫자로 시작할 수 없습니다. 식별자의 길이는 최대 255자까지 가능하지만 변환기는 처음 32자만 받아들이고 나머지는 무시합니다. 옵션을 사용하여 가능한 식별자의 길이를 조정할 수 있습니다. 명령줄 mv. 또한 번역자에게 대문자와 소문자를 구별하거나 차이점을 무시하도록 지시할 수 있습니다(기본적으로 수행됨).

^ 어셈블리 언어 명령.

어셈블러 명령은 요구 사항을 컴퓨터로 전송하는 기능, 논리적 비교 및 ​​프로그램 구성을 위해 프로그램에서 제어를 전송하는 메커니즘(루프 및 점프)을 엽니다. 그러나 프로그래밍 작업은 그렇게 간단하지 않습니다. 대부분의 프로그램에는 특정 요구 사항에 도달할 때까지 여러 명령이 반복되는 일련의 루프와 수행할 여러 작업을 결정하기 위한 다양한 검사가 포함되어 있습니다. 일부 명령은 명령 포인터에서 오프셋 값을 직접 수정하여 정상적인 단계 시퀀스를 변경하여 제어를 전송할 수 있습니다. 앞에서 언급했듯이 프로세서마다 다른 명령이 있지만 프로세서 80186, 80286 및 80386에 대한 몇 가지 명령을 고려할 것입니다.

특정 명령을 실행한 후 플래그 상태를 설명하기 위해 eflags 플래그 레지스터의 구조를 반영하는 표에서 선택한 항목을 사용합니다.

이 표의 맨 아래 행에는 명령이 실행된 후 플래그 값이 나열됩니다. 이 경우 다음 표기법이 사용됩니다.

1 - 명령이 실행된 후 플래그가 설정됩니다(1과 같음).

0 - 명령이 실행된 후 플래그가 재설정됩니다(0과 같음).

r - 플래그의 값은 명령의 결과에 따라 다릅니다.

명령을 실행한 후 플래그는 정의되지 않습니다.

공백 - 명령을 실행한 후 플래그가 변경되지 않습니다.

다음 표기법은 구문 다이어그램에서 피연산자를 나타내는 데 사용됩니다.

r8, r16, r32 - 크기 바이트, 워드 또는 더블 워드 레지스터 중 하나의 피연산자;

m8, m16, m32, m48 - 바이트, 워드, 더블 워드 또는 48비트 메모리 크기의 피연산자;

i8, i16, i32 - 크기 바이트, 워드 또는 더블 워드의 직접 피연산자;

a8, a16, a32 - 코드 세그먼트의 상대 주소(오프셋).

명령(알파벳순):

*이 명령은 자세히 설명되어 있습니다.

추가하다
(덧셈)

덧셈

^ 명령 개요:

대상, 소스 추가

목적: 바이트, 워드 또는 더블 워드 차원의 두 소스 및 대상 피연산자 추가.

작업 알고리즘:

소스 및 대상 피연산자를 추가합니다.

추가 결과를 수신기에 기록합니다.

플래그를 설정합니다.

명령 실행 후 플래그 상태:

애플리케이션:
add 명령은 두 개의 정수 피연산자를 더하는 데 사용됩니다. 추가 결과는 첫 번째 피연산자의 주소에 배치됩니다. 추가 결과가 대상 피연산자의 범위를 벗어나는 경우(오버플로 발생) cf 플래그를 분석한 다음 가능하면 adc 명령을 사용하여 이 상황을 고려해야 합니다. 예를 들어, 레지스터 ax와 메모리 영역 ch의 값을 더해보자. 추가할 때 오버플로 가능성을 고려해야 합니다.

레지스터 플러스 레지스터 또는 메모리:

|000000dw|modregr/rm|

레지스터 AX(AL) 더하기 즉치값:

|0000010w|--데이터--|w=1인 경우 데이터|

레지스터 또는 메모리 더하기 즉치값:

|100000sw|mod000r/m|--데이터--|BW=01인 경우 데이터|

부르다
(부르다)

프로시저 또는 작업 호출

^ 명령 개요:

목적:

스택에 리턴 포인트의 주소를 저장하여 클로즈 또는 파 프로시저로 제어를 이전합니다.

작업 전환.

작업 알고리즘:
피연산자 유형에 따라 결정됩니다.

레이블이 가깝습니다 - eip / ip 명령 포인터의 내용이 스택에 푸시되고 레이블에 해당하는 새 주소 값이 동일한 레지스터에 로드됩니다.

먼 레이블 - eip/ip 및 cs 명령 포인터의 내용이 스택에 푸시됩니다. 그런 다음 원거리 마크에 해당하는 새 주소 값이 동일한 레지스터에 로드됩니다.

R16, 32 또는 m16, 32 - 제어가 전송되는 현재 명령어 세그먼트의 오프셋을 포함하는 레지스터 또는 메모리 셀을 정의합니다. 제어가 전송되면 eip/ip 명령 포인터의 내용이 스택으로 푸시됩니다.

메모리 포인터 - 호출되는 프로시저에 대한 4바이트 또는 6바이트 포인터를 포함하는 메모리 위치를 정의합니다. 이러한 포인터의 구조는 2+2 또는 2+4바이트입니다. 이러한 포인터의 해석은 마이크로프로세서의 작동 모드에 따라 다릅니다.

^ 명령 실행 후 플래그 상태(작업 전환 제외):

명령 실행은 플래그에 영향을 주지 않습니다.

태스크가 전환되면 전환되는 태스크의 TSS 상태 세그먼트에 있는 eflags 레지스터에 대한 정보에 따라 플래그의 값이 변경됩니다.
애플리케이션:
호출 명령을 사용하면 반환 지점의 주소를 유지하면서 서브루틴으로 제어를 유연하고 다변량으로 이전하도록 구성할 수 있습니다.

개체 코드(네 가지 형식):

세그먼트의 직접 주소 지정:

|11101000|표시 낮음|딥 높음|

세그먼트의 간접 주소 지정:

|11111111|mod010r/m|

세그먼트 간 간접 주소 지정:

|11111111|mod011r/m|

세그먼트 간 직접 주소 지정:

|10011010|오프셋-로우|오프셋-하이|세그-로우|세그-하이|

CMP
(피연산자 비교)

피연산자 비교

^ 명령 개요:

cmp 피연산자1, 피연산자2

목적: 두 피연산자의 비교.

작업 알고리즘:

빼기 수행(operand1-operand2);

결과에 따라 플래그를 설정하고, operand1 및 operand2를 변경하지 마십시오(즉, 결과를 저장하지 않음).

애플리케이션:
이 명령피연산자가 변경되지 않는 동안 빼기로 두 피연산자를 비교하는 데 사용됩니다. 플래그는 명령 실행 결과로 설정됩니다. cmp 명령어는 조건부 점프 명령어 및 setcc by value 명령어와 함께 사용됩니다.

개체 코드(세 가지 형식):

등록 또는 등록된 메모리:

|001110dw|modreg/m|

레지스터 AX(AL)의 즉시 값:

|0011110w|--데이터--|w=1인 경우 데이터|

레지스터 또는 메모리를 사용한 즉시 값:

|100000sw|mod111r/m|--데이터--|sw=0인 경우 데이터|

12월
(1씩 감소 피연산자)

피연산자 1씩 감소

^ 명령 개요:

12월 피연산자

목적: 메모리 또는 레지스터의 피연산자 값을 1씩 감소시킵니다.

작업 알고리즘:
명령어는 피연산자에서 1을 뺍니다. 명령 실행 후 플래그 상태:

애플리케이션:
dec 명령은 메모리 또는 레지스터의 바이트, 워드, 더블 워드 값을 하나씩 감소시키는 데 사용됩니다. 이 명령은 cf 플래그에 영향을 주지 않습니다.

등록: |01001reg|

^ 레지스터 또는 메모리: |1111111w|mod001r/m|

DIV
(부호 없는 DIVide)

서명되지 않은 부문

명령 체계:

div 구분선

목적: 두 개의 부호 없는 이진 값에 대해 나누기 연산을 수행합니다.

^ 작업 알고리즘:
이 명령에는 두 개의 피연산자(피제수 및 제수)가 필요합니다. 피제수는 암시적으로 지정되며 그 크기는 명령에 지정된 제수의 크기에 따라 다릅니다.

제수가 바이트이면 피제수는 레지스터 ax에 있어야 합니다. 연산 후, 몫은 al에, 나머지는 ah에 배치됩니다.

제수가 단어인 경우 피제수는 레지스터 쌍 dx:ax에 있어야 하며 피제수의 하위 부분은 ax에 있어야 합니다. 연산 후 몫은 ax에, 나머지는 dx에 배치됩니다.

제수가 더블 워드인 경우 피제수는 레지스터 쌍 edx:eax에 있어야 하며 피제수의 하위 부분은 eax에 있어야 합니다. 연산 후 몫은 eax에 나머지는 edx에 배치됩니다.

^ 명령 실행 후 플래그 상태:

애플리케이션:
이 명령은 피연산자의 정수 나누기를 수행하여 나눗셈 결과를 몫으로 반환하고 나눗셈의 나머지를 반환합니다. 나누기 작업을 수행할 때 예외가 발생할 수 있습니다. 0 - 나누기 오류. 이 상황은 두 경우 중 하나에서 발생합니다. 제수가 0이거나 몫이 너무 커서 eax/ax/al 레지스터에 맞지 않습니다.

개체 코드:

|1111011w|mod110r/m|

지능
(방해하다)

인터럽트 서비스 루틴 호출

^ 명령 개요:

int 인터럽트_번호

목적: 명령 피연산자가 지정한 인터럽트 번호로 인터럽트 서비스 루틴을 호출합니다.

^ 작업 알고리즘:

eflags/flags 레지스터와 반환 주소를 스택에 푸시합니다. 반환 주소를 쓸 때 cs 세그먼트 레지스터의 내용을 먼저 쓴 다음 eip/ip 명령 포인터의 내용을 씁니다.

if 및 tf 플래그를 0으로 재설정합니다.

지정된 번호의 인터럽트 핸들러로 제어를 전송합니다. 제어 전송 메커니즘은 마이크로프로세서의 작동 모드에 따라 다릅니다.

^ 명령 실행 후 플래그 상태:

애플리케이션:
구문에서 볼 수 있듯이 이 명령에는 두 가지 형식이 있습니다.

int 3 - 자체 opcode 0cch를 가지며 1바이트를 차지합니다. 이러한 상황은 명령어의 첫 번째 바이트를 대체하여 중단점을 설정하기 위해 다양한 소프트웨어 디버거에서 사용하는 것을 매우 편리하게 만듭니다. 명령 시퀀스에서 opcode 0cch가 있는 명령을 만나는 마이크로 프로세서는 소프트웨어 디버거와 통신하는 역할을 하는 벡터 번호 3으로 인터럽트 처리기를 호출합니다.

명령의 두 번째 형식은 2바이트 길이이고 opcode는 0cdh이며 0-255 범위의 벡터 번호로 인터럽트 서비스 루틴에 대한 호출을 시작할 수 있습니다. 언급한 바와 같이 제어 전송의 특징은 마이크로프로세서의 작동 모드에 따라 다릅니다.

개체 코드(두 가지 형식):

등록: |01000reg|

^ 레지스터 또는 메모리: |1111111w|mod000r/m|

JCC
JCXZ/JECXZ
(조건이면 점프)

(CX=0이면 점프/ECX=0이면 점프)

조건을 만족하면 점프

CX/ECX가 0이면 점프

^ 명령 개요:

jcc 레이블
jcxz 레이블
jecxz 레이블

목적: 일부 조건에 따라 현재 명령 세그먼트 내에서 전환합니다.

^ 명령 알고리즘(jcxz/jecxz 제외):
opcode에 따라 플래그 상태 확인(확인 중인 조건을 반영함):

테스트 중인 조건이 참이면 피연산자가 나타내는 셀로 이동합니다.

확인 중인 조건이 거짓이면 제어를 다음 명령으로 넘깁니다.

jcxz/jecxz 명령 알고리즘:
ecx/cx 레지스터의 내용이 0과 같은 조건 확인:

체크된 상태라면

조립 언어 명령어 구조 기계 명령어 수준의 프로그래밍은 컴퓨터 프로그래밍이 가능한 최소 수준입니다. 기계 명령어 시스템은 기계 하드웨어에 명령을 내림으로써 필요한 작업을 구현하기에 충분해야 합니다. 각 기계 명령어는 두 부분으로 구성됩니다. "무엇을 할 것인가"를 정의하는 조작 부분과 처리 대상, 즉 "무엇을 할 것인가"를 정의하는 피연산자입니다. 어셈블리 언어로 작성된 마이크로프로세서의 기계 명령어는 다음 형식을 갖는 한 줄입니다. 레이블 명령어/지시 피연산자(들) ; 주석 레이블, 명령/지시문 및 피연산자는 하나 이상의 공백 또는 탭 문자로 구분됩니다. 명령어 피연산자는 쉼표로 구분됩니다.

어셈블리 언어 명령어의 구조 어셈블리 언어 명령어는 마이크로프로세서가 수행해야 하는 작업을 컴파일러에 알려줍니다. 어셈블리 지시문은 어셈블리 프로세스 또는 출력 파일의 속성에 영향을 주는 프로그램 텍스트에 지정된 매개변수입니다. 피연산자는 데이터의 초기 값(데이터 세그먼트에서) 또는 명령에 의해 실행될 요소(코드 세그먼트에서)를 지정합니다. 명령에는 하나 또는 두 개의 피연산자가 있거나 피연산자가 없을 수 있습니다. 피연산자의 수는 명령어 코드에 의해 암시적으로 지정됩니다. 명령이나 지시문을 다음 줄에서 계속해야 하는 경우 백슬래시 문자 "" 가 사용됩니다. 기본적으로 어셈블러는 명령과 지시문에서 대문자와 소문자를 구분하지 않습니다. 지시문 및 명령 예 Count db 1 ; 이름, 지시문, 하나의 피연산자 mov eax, 0 ; 명령, 피연산자 2개

식별자는 변수 이름과 레이블 이름을 지정하는 데 사용되는 유효한 문자 시퀀스입니다. 식별자는 다음 문자 중 하나 이상으로 구성될 수 있습니다. 라틴 알파벳의 모든 문자; 0에서 9까지의 숫자; 특수 문자: _, @, $, ? . 레이블의 첫 번째 문자로 점을 사용할 수 있습니다. 예약된 어셈블러 이름(지시문, 연산자, 명령 이름)은 식별자로 사용할 수 없습니다. 식별자의 첫 번째 문자는 문자 또는 특수 문자여야 합니다. 최대 길이식별자는 255자이지만 번역기는 처음 32자를 받아들이고 나머지는 무시됩니다. 어셈블러 지시문을 포함하지 않는 행에 작성된 모든 레이블은 콜론 ":"으로 끝나야 합니다. 레이블, 명령(지시문) 및 피연산자는 문자열의 특정 위치에서 시작할 필요가 없습니다. 프로그램의 가독성을 높이기 위해 열에 작성하는 것이 좋습니다.

레이블 어셈블러 지시문이 포함되지 않은 행에 기록된 모든 레이블은 콜론 ":"으로 끝나야 합니다. 레이블, 명령(지시문) 및 피연산자는 문자열의 특정 위치에서 시작할 필요가 없습니다. 프로그램의 가독성을 높이기 위해 열에 작성하는 것이 좋습니다.

주석 프로그램에서 주석을 사용하면 특히 명령 세트의 목적이 불분명한 경우 명확성이 향상됩니다. 주석은 소스 모듈의 모든 줄에서 세미콜론(;)으로 시작합니다. "의 오른쪽에 있는 모든 문자; ' 줄 끝에 주석이 있습니다. 주석에는 "공백"을 포함하여 인쇄 가능한 모든 문자가 포함될 수 있습니다. 주석은 전체 행에 걸쳐 있거나 같은 행에서 명령을 따를 수 있습니다.

어셈블리 언어 프로그램의 구조 어셈블리 언어 프로그램은 모듈이라는 여러 부분으로 구성될 수 있으며 각 부분은 하나 이상의 데이터, 스택 및 코드 세그먼트를 정의할 수 있습니다. 모든 완전한 어셈블리 언어 프로그램에는 실행이 시작되는 하나의 기본 또는 기본 모듈이 포함되어야 합니다. 모듈은 다음을 포함할 수 있습니다. 프로그램 세그먼트, 적절한 지시문을 사용하여 선언된 데이터 및 스택 세그먼트.

메모리 모델 세그먼트를 선언하기 전에 지시문을 사용하여 메모리 모델을 지정해야 합니다. MODEL 수정자 memory_model, calling_convention, OS_type, stack_parameter 기본 어셈블리 언어 메모리 모델: 메모리 모델 코드 어드레싱 데이터 어드레싱 운영 체제코드 및 데이터 인터리빙 TINY NEAR MS-DOS 허용 SMALL NEAR MS-DOS, Windows 아니오 MEDIUM FAR NEAR MS-DOS, Windows 아니오 COMPACT NEAR FAR MS-DOS, Windows 아니오 LARGE FAR MS-DOS, Windows 아니오 HUGE FAR MS-DOS, Windows 아니요 NEAR Windows 2000, Windows XP, Windows 허용 FLAT NEAR NT,

메모리 모델 작은 모델은 16비트 MS-DOS 응용 프로그램에서만 작동합니다. 이 모델에서 모든 데이터와 코드는 하나의 물리적 세그먼트에 상주합니다. 이 경우 프로그램 파일의 크기는 64KB를 초과하지 않습니다. 작은 모델은 하나의 코드 세그먼트와 하나의 데이터 세그먼트를 지원합니다. 이 모델을 사용할 때 데이터 및 코드는 근거리(near)로 처리됩니다. 중간 모델은 여러 코드 세그먼트와 하나의 데이터 세그먼트를 지원하며 기본적으로 코드 세그먼트의 모든 링크는 먼(멀리) 것으로 간주되고 데이터 세그먼트의 링크는 가까운(가까운) 것으로 간주됩니다. 컴팩트 모델은 원거리 데이터 주소 지정(far)을 사용하는 여러 데이터 세그먼트와 근거리 데이터 주소 지정(near)을 사용하는 하나의 코드 세그먼트를 지원합니다. 대형 모델은 여러 코드 세그먼트와 여러 데이터 세그먼트를 지원합니다. 기본적으로 모든 코드 및 데이터 참조는 먼 것으로 간주됩니다. 거대 모델은 대용량 메모리 모델과 거의 동일합니다.

메모리 모델 플랫 모델은 세그먼트화되지 않은 프로그램 구성을 가정하며 32비트 운영 체제에서만 사용됩니다. 이 모델은 데이터와 코드가 동일한 32비트 세그먼트에 있다는 점에서 작은 모델과 유사합니다. 지시 전에 플랫 모델에 대한 프로그램을 개발합니다. 모델 플랫은 다음 지시문 중 하나를 배치해야 합니다. . 386, . 486, . 586 나. 686. 프로세서 선택 지시어의 선택은 프로그램을 작성할 때 사용할 수 있는 명령 집합을 결정합니다. 프로세서 선택 지시문 뒤의 문자 p는 보호된 작동 모드를 의미합니다. 모든 주소와 포인터가 32비트인 데이터 및 코드 주소 지정이 가깝습니다.

메모리 모델. MODEL 수정자 memory_model, calling_convention, OS_type, stack_parameter 수정자 매개변수는 세그먼트 유형을 정의하는 데 사용되며 다음 값을 사용할 수 있습니다. use 16(선택한 모델의 세그먼트가 16비트로 사용됨) use 32(선택한 모델의 세그먼트가 사용됨) 32비트로). calling_convention 매개변수는 고급 언어(C++, Pascal)를 비롯한 다른 언어에서 프로시저를 호출할 때 매개변수를 전달하는 방법을 결정하는 데 사용됩니다. 매개변수는 C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL 값을 사용할 수 있습니다.

메모리 모델. MODEL 수정자 memory_model, calling_convention, OS_type, stack_parameter OS_type 매개변수는 기본적으로 OS_DOS이며 on 이 순간이 매개변수에 지원되는 유일한 값입니다. stack_param 매개변수는 다음과 같이 설정됩니다. NEARSTACK(SS 레지스터는 DS와 동일, 데이터 및 스택 영역은 동일한 물리적 세그먼트에 위치) FARSTACK(SS 레지스터는 DS와 동일하지 않음, 데이터 및 스택 영역은 서로 다른 물리적 세그먼트에 위치). 기본값은 NEARSTACK입니다.

"아무것도 하지 않는" 프로그램의 예. 686 P. 모델 플랫, STDCALL. 데이터. CODE START: RET END START RET - 마이크로프로세서 명령. 프로그램의 올바른 종료를 보장합니다. 프로그램의 나머지 부분은 번역기의 작동과 관련이 있습니다. . 686 P - 펜티엄 6(펜티엄 II) 보호 모드 명령이 허용됩니다. 이 지시문은 프로세서 모델을 지정하여 지원되는 어셈블러 명령어 세트를 선택합니다. . MODEL FLAT, stdcall - 플랫 메모리 모델. 이 메모리 모델은 Windows 운영 체제에서 사용됩니다. stdcall은 사용할 프로시저 호출 규칙입니다.

"아무것도 하지 않는" 프로그램의 예. 686 P. 모델 플랫, STDCALL. 데이터. 코드 시작: RET 종료 시작 . DATA - 데이터를 포함하는 프로그램 세그먼트. 이 프로그램스택을 사용하지 않으므로 세그먼트. 스택이 없습니다. . CODE - 코드를 포함하는 프로그램의 세그먼트. 시작 - 라벨. END START - 프로그램의 끝과 프로그램이 레이블 START에서 시작되어야 한다는 컴파일러에 대한 메시지입니다. 모든 프로그램은 끝을 표시하는 END 지시문을 포함해야 합니다. 소스 코드프로그램들. END 지시어 다음의 모든 줄은 무시됩니다. END 지시어 뒤의 레이블은 컴파일러에게 프로그램 실행이 시작되는 주 모듈의 이름을 알려줍니다. 프로그램에 하나의 모듈이 포함된 경우 END 지시문 뒤의 레이블을 생략할 수 있습니다.

어셈블리 언어 번역기 번역기는 프로그램 또는 기술적 수단프로그래밍 언어 중 하나의 프로그램을 대상 언어의 프로그램으로 변환하는 객체 코드라고 합니다. 기계 명령어 니모닉을 지원하는 것 외에도 각 번역기에는 고유한 지시문 및 매크로 세트가 있으며 종종 다른 어떤 것과도 호환되지 않습니다. 어셈블리 언어 변환기의 주요 유형은 다음과 같습니다. MASM(Microsoft Assembler), TASM(Borland Turbo Assembler), FASM(Flat Assembler) - Tomasz Gryshtar(폴란드어)가 작성한 자유 배포 다중 패스 어셈블러, NASM(Netwide Assembler) - a Intel x 아키텍처 86용 무료 어셈블러는 Simon Tatham이 Julian Hall과 함께 만들었으며 현재 Source의 소규모 개발 팀에서 개발 중입니다. 노. 그물.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Microsoft Visual Studio 2005에서 프로그램 변환 1) 파일->새로 만들기->프로젝트를 선택하여 프로젝트를 생성합니다. 메뉴 그리고"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.!}

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Microsoft Visual Studio 2005의 프로그램 변환 2) 프로젝트 트리(View->Solution Explorer)에서 추가"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Microsoft Visual Studio 2005에서 프로그램 번역 3) Code C++ 파일 형식을 선택하되 확장자를 포함하여 이름을 지정합니다. asm:

Microsoft Visual Studio 2005에서 프로그램 번역 5) 컴파일러 옵션을 설정합니다. 프로젝트 파일 메뉴 Custom Build Rules…에서 오른쪽 버튼을 선택합니다.

Microsoft Visual Studio 2005에서 프로그램을 번역하고 나타나는 창에서 Microsoft Macro Assembler를 선택합니다.

Microsoft Visual Studio 2005에서 프로그램 번역 hello 파일에서 오른쪽 버튼으로 확인하십시오. 속성 메뉴에서 프로젝트 트리의 asm을 선택하고 일반->도구: Microsoft Macro Assembler를 설정합니다.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Microsoft Visual Studio 2005에서 프로그램 번역 6) Build->Build hello.prj를 선택하여 파일을 컴파일합니다. ."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

OS Windows 프로그래밍 OS Windows 프로그래밍은 API 기능(애플리케이션 프로그램 인터페이스, 즉 소프트웨어 애플리케이션 인터페이스)의 사용을 기반으로 합니다. 그들의 수는 2000에 이릅니다. Windows 용 프로그램은 주로 이러한 호출로 구성됩니다. 모든 상호 작용 외부 장치운영 체제의 자원은 원칙적으로 이러한 기능을 통해 발생합니다. 수술실 윈도우 시스템플랫 메모리 모델을 사용합니다. 모든 메모리 위치의 주소는 하나의 32비트 레지스터의 내용에 따라 결정됩니다. Windows용 프로그램 구조에는 대화 상자(기본 창은 대화 상자임), 콘솔 또는 창 없는 구조, 클래식 구조(창, 프레임)의 세 가지 유형이 있습니다.

부르다 윈도우 기능 API 도움말 파일에서 모든 API 함수는 function_name(FA 1, FA 2, FA 3) 유형으로 표시됩니다. 유형 – 반환 값 유형; FAX – 형식 인수 목록(예: int Message). 상자(HWND h. Wnd, LPCTSTR lp. 텍스트, LPCTSTR lp. 캡션, UINT u. 유형); 이 기능메시지와 종료 버튼이 있는 창을 표시합니다. 매개변수의 의미: h. Wnd - 메시지 창이 나타날 창에 대한 핸들, lp. 텍스트 - 창에 표시될 텍스트, lp. 캡션 - 창 제목의 텍스트, u. 유형 - 창 유형, 특히 종료 버튼의 수를 지정할 수 있습니다.

메시지에서 Windows API 함수를 호출합니다. 상자(HWND h. Wnd, LPCTSTR lp. 텍스트, LPCTSTR lp. 캡션, UINT u. 유형); 거의 모든 API 함수 매개변수는 실제로 32비트 정수입니다. HWND는 32비트 정수, LPCTSTR은 32비트 문자열 포인터, UINT는 32비트 정수입니다. 접미사 "A"는 종종 최신 버전의 함수로 이동하기 위해 함수 이름에 추가됩니다.

메시지에서 Windows API 함수를 호출합니다. 상자(HWND h. Wnd, LPCTSTR lp. 텍스트, LPCTSTR lp. 캡션, UINT u. 유형); MASM을 사용하는 경우 이름 끝에 @N N을 추가해야 합니다. 전달된 인수가 스택에서 차지하는 바이트 수입니다. Win 32 API 함수의 경우 이 숫자는 인수의 수 n x 4(각 인수의 바이트)로 정의할 수 있습니다. N=4*n. 함수를 호출하려면 어셈블러의 CALL 명령어를 사용합니다. 이 경우 함수에 대한 모든 인수는 스택(PUSH 명령)을 통해 전달됩니다. 인수 전달 방향: LEFT TO RIGHT - BOTTOM UP. 인수 u가 스택에 먼저 푸시됩니다. 유형. 지정된 함수를 호출하면 다음과 같이 표시됩니다. CALL 메시지. 상자. [이메일 보호]

메시지에서 Windows API 함수를 호출합니다. 상자(HWND h. Wnd, LPCTSTR lp. 텍스트, LPCTSTR lp. 캡션, UINT u. 유형); API 함수를 실행한 결과는 일반적으로 EAX 레지스터에 반환되는 정수입니다. OFFSET 지시문은 "세그먼트 오프셋" 또는 고급 언어 용어로 문자열 시작에 대한 "포인터"입니다. C의 #define과 같은 EQU 지시문은 상수를 정의합니다. EXTERN 지시문은 함수 또는 식별자가 모듈 외부에 있음을 컴파일러에 알립니다.

"안녕하세요 여러분!" 프로그램의 예 . 686 P. 모델 플랫, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "나의 첫 번째 프로그램", 0 STR 2 DB "안녕하세요 여러분!", 0 HW DD ? 외부 메시지. 상자. [이메일 보호]: 가까운. CODE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL 메시지를 푸시합니다. 상자. [이메일 보호] RET 종료 시작

INVOKE 지시문 MASM 언어 번역기는 또한 매크로 도구를 사용하여 함수 호출을 단순화할 수 있도록 합니다. INVOKE 지시어: INVOKE function, parameter1, parameter2, ... 함수 호출에 @16을 추가할 필요가 없습니다. 매개변수는 함수 설명에 제공된 순서대로 정확하게 작성됩니다. 변환기 매크로는 매개변수를 스택에 푸시합니다. INVOKE 지시문을 사용하려면 메시지 형식의 PROTO 지시문을 사용하는 함수 프로토타입에 대한 설명이 있어야 합니다. 상자. 프로토타입: DWORD, : DWORD

항목 2.5 프로세서 프로그래밍 기본 사항

프로그램의 길이가 길어질수록 다양한 작업에 대한 코드를 기억하기가 더 어려워집니다. 니모닉은 이와 관련하여 약간의 도움을 제공합니다.

기호 명령어 인코딩 언어를 호출합니다. 어셈블러.

어셈블리어각 명령문이 정확히 하나의 기계 명령에 해당하는 언어입니다.

집회어셈블리 언어에서 프로그램 변환, 즉 작업의 기호 이름을 기계 코드로 바꾸고 기호 주소를 절대 또는 상대 숫자로 바꾸고 라이브러리 프로그램을 포함하고 특정 매개 변수를 지정하여 기호 명령어 시퀀스를 생성하여 기계어로 프로그램을 준비합니다. 마이크로 명령어에서. 이 프로그램은 일반적으로 ROM에 배치되거나 일부 외부 매체에서 RAM에 입력됩니다.

어셈블리 언어에는 고급 언어와 구별되는 몇 가지 기능이 있습니다.

1. 이것은 어셈블리 언어 문과 기계 명령어 간의 일대일 대응입니다.

2. 어셈블리 언어 프로그래머는 대상 시스템에 있는 모든 개체 및 명령에 액세스할 수 있습니다.

기계 지향 언어 프로그래밍의 기본 사항에 대한 이해는 다음에 유용합니다.



PC 아키텍처에 대한 더 나은 이해와 더 나은 컴퓨터 사용;

응용 문제를 해결하기 위한 프로그램을 위한 보다 합리적인 알고리즘 구조를 개발합니다.

소스 프로그램이 손실된 경우 확장명이 .exe 및 .com인 실행 프로그램을 보고 수정하는 기능(이러한 프로그램을 DEBUG 프로그램 디버거로 호출하고 디스플레이를 어셈블리 언어로 디컴파일하여 );

가장 중요한 작업을 해결하기 위한 프로그램 컴파일(기계 지향 언어로 컴파일된 프로그램은 일반적으로 더 효율적입니다. 고급 언어에서 번역된 결과로 얻은 프로그램보다 30-60% 더 짧고 빠릅니다.)

사용되는 고급 언어나 OS 서비스 프로시저를 사용하여 구현할 수 없는 경우 별도의 조각으로 메인 프로그램에 포함된 프로시저의 구현을 위해.

어셈블리 언어 프로그램은 같은 제품군의 컴퓨터에서만 실행될 수 있는 반면 고급 언어로 작성된 프로그램은 잠재적으로 다른 시스템에서 실행될 수 있습니다.

어셈블리 언어 알파벳은 ASCII 문자로 구성됩니다.

숫자는 정수일 뿐입니다. 구별하다:

문자 B로 끝나는 이진수;

D로 끝나는 십진수;

N으로 끝나는 16진수.

, 레지스터, 데이터 표현

특정 일련의 MP의 경우 개별 프로그래밍 언어인 어셈블리 언어가 사용됩니다.

어셈블리 언어는 기계 코드와 고급 언어 사이의 중간 위치를 차지합니다. 이 언어로 프로그래밍하는 것이 더 쉽습니다. 어셈블리 언어 프로그램은 고급 언어(어셈블러보다 프로그래머에게 더 쉬운)의 프로그램보다 더 합리적으로 특정 기계(더 정확하게는 MP)의 기능을 사용합니다. MP KR580VM80용 어셈블리 언어를 예로 들어 기계 지향 언어로 프로그래밍하는 기본 원칙을 살펴보겠습니다. 언어 프로그래밍의 경우 일반적인 기술이 사용됩니다. 프로그램을 녹음하는 특정 기술은 대상 MP의 아키텍처 및 명령 시스템 기능과 관련됩니다.

소프트웨어 모델 MP KR580VM80 기반 마이크로프로세서 시스템

그림 1에 따른 MPS의 프로그램 모델

MP 포트 메모리

에스 교류

그림 1

프로그래머의 관점에서 KR580VM80 MP에는 다음과 같은 프로그램 액세스 가능 레지스터가 있습니다.

– 8비트 누산기 레지스터. MP의 주 레지스터입니다. ALU에서 수행되는 모든 연산에는 누산기에서 처리할 피연산자 중 하나를 배치하는 것이 포함됩니다. ALU의 연산 결과도 일반적으로 A에 저장됩니다.

B, C, D, E, H, L– 8비트 범용 레지스터(RON). 내부 메모리의원. 처리된 정보와 작업 결과를 저장하도록 설계되었습니다. 레지스터에서 16비트 워드를 처리할 때 BC, DE, HL 쌍이 형성되고 이중 레지스터를 첫 번째 문자(B, D, H)라고 합니다. 레지스터 쌍에서 첫 번째 레지스터가 가장 높습니다. 데이터를 저장하고 RAM 셀의 16비트 주소를 저장하는 데 사용되는 H, L 레지스터에는 특별한 속성이 있습니다.

플로리다– 플래그 레지스터(기능 레지스터) 산술 및 논리 연산을 수행한 결과의 5가지 기능을 MP에 저장하는 8비트 레지스터입니다. 그림에 따른 FL 형식

비트 C(CY - 캐리) - 캐리, 산술 연산을 수행할 때 상위 바이트에서 캐리가 있는 경우 1로 설정됩니다.

비트 P(패리티) - 패리티는 결과 비트의 단위 수가 짝수인 경우 1로 설정됩니다.

AC 비트는 결과의 하위 테트라드에서 캐리 값을 저장하도록 설계된 추가 캐리입니다.

비트 Z(영) - 연산 결과가 0이면 1로 설정됩니다.

결과가 음수이면 S(부호) 비트가 1로 설정되고 양수이면 0으로 설정됩니다.

SP-- 16비트 레지스터인 스택 포인터는 스택에 입력된 마지막 바이트가 기록된 메모리 위치의 주소를 저장하도록 설계되었습니다.

RS– 프로그램 카운터(프로그램 카운터), 16비트 레지스터, 다음 실행 가능한 명령어의 주소를 저장하도록 설계되었습니다. 프로그램 카운터의 내용은 다음 명령어 바이트를 가져온 직후 자동으로 1씩 증가합니다.

주소 0000H - 07FF의 초기 메모리 영역에 위치 제어 프로그램및 데모 프로그램. 이것은 ROM 영역입니다.

0800 - 0AFF - 연구 중인 프로그램을 기록하기 위한 주소 영역. (램).

0В00 - 0ВВ0 - 데이터 기록을 위한 주소 영역. (램).

0BB0은 스택의 시작 주소입니다. (램).

스택은 데이터 또는 주소의 임시 저장을 위해 설계된 특별히 구성된 RAM 영역입니다. 스택에 마지막으로 푸시된 숫자는 스택에서 꺼낸 첫 번째 숫자입니다. 스택 포인터는 정보가 저장된 마지막 스택 위치의 주소를 저장합니다. 서브루틴이 호출되면 메인 프로그램의 리턴 주소가 자동으로 스택에 저장됩니다. 일반적으로 각 서브루틴 시작 시 실행과 관련된 모든 레지스터의 내용이 스택에 저장되고 서브루틴 종료 시 스택에서 복원됩니다.

어셈블리 언어 데이터 형식 및 명령 구조

메모리 MP KR580VM80은 바이트라고 하는 8비트 단어의 배열입니다. 각 바이트는 메모리 셀 시퀀스에서 위치를 결정하는 고유한 16비트 주소를 가집니다. MP는 ROM과 RAM을 모두 포함할 수 있는 65536바이트의 메모리 주소를 지정할 수 있습니다.

데이터 형식

데이터는 8비트 워드로 메모리에 저장됩니다.

D7 D6 D5 D4 D3 D2 D1 D0

최하위 비트는 비트 0이고 최상위 비트는 비트 7입니다.

명령은 형식, 즉 특정 기능 필드로 바이트 단위로 분할되는 할당된 비트 수로 특징지어집니다.

명령 형식

MP KR580VM80 명령에는 1바이트, 2바이트 또는 3바이트 형식이 있습니다. 멀티바이트 명령어는 인접한 PL에 배치해야 합니다. 명령의 형식은 수행 중인 작업의 특성에 따라 다릅니다.

명령의 첫 번째 바이트에는 니모닉 형식으로 작성된 opcode가 포함됩니다.

명령의 형식과 실행 중 데이터에 대해 MP가 수행해야 하는 작업, 주소 지정 방법을 정의하고 데이터 위치에 대한 정보도 포함할 수 있습니다.

두 번째 및 세 번째 바이트에는 연산할 데이터 또는 데이터 위치를 나타내는 주소가 포함될 수 있습니다. 연산이 수행되는 데이터를 피연산자라고 합니다.

그림 2에 따른 단일 바이트 명령 형식

그림 4

어셈블리 언어 명령어에서 opcode는 영어 단어 쓰기의 약식 형식인 니모닉 표기법을 사용합니다. 니모닉(그리스어 니모닉 - 암기 기술)을 사용하면 기능적 목적에 따라 명령을 더 쉽게 기억할 수 있습니다.

실행하기 전에 소스 프로그램은 어셈블러라는 번역 프로그램을 사용하여 코드 조합 언어인 기계어로 번역되며, 이 형식으로 MP의 메모리에 배치된 다음 명령을 실행할 때 사용됩니다.


주소 지정 방법

모든 피연산자 코드(입력 및 출력)는 어딘가에 있어야 합니다. 그들은 MP의 내부 레지스터에 있을 수 있습니다(가장 편리하고 빠른 옵션). 시스템 메모리에 위치할 수 있습니다(가장 일반적인 옵션). 마지막으로 I/O 장치에 있을 수 있습니다(가장 드문 경우). 피연산자의 위치는 명령 코드에 의해 결정됩니다. 존재하다 다른 방법, 명령 코드는 입력 피연산자를 가져올 위치와 출력 피연산자를 넣을 위치를 결정할 수 있습니다. 이러한 방법을 주소 지정 방법이라고 합니다.

MP KR580VM80의 ​​경우 다음 주소 지정 방법이 있습니다.

즉각적인;

등록하다;

간접;

스택.

즉각적인 주소 지정은 피연산자(입력)가 명령 코드 바로 뒤에 메모리에 있다고 가정합니다. 피연산자는 일반적으로 어딘가에 보내거나 무언가에 추가해야 하는 상수입니다. 데이터는 명령의 두 번째 또는 두 번째 및 세 번째 바이트에 포함되며 하위 데이터 바이트는 두 번째 명령 바이트에, 상위 데이터 바이트는 세 번째 명령 바이트에서.

똑바로 (일명 절대) 주소 지정은 피연산자(입력 또는 출력)가 명령 코드 바로 뒤에 있는 프로그램 내부에 코드가 있는 주소의 메모리에 있다고 가정합니다. 3바이트 명령에 사용됩니다.

등록하다 주소 지정은 피연산자(입력 또는 출력)가 내부 MP 레지스터에 있다고 가정합니다. 단일 바이트 명령에 사용

간접 (암시적) 주소 지정은 MP의 내부 레지스터가 피연산자 자체가 아니라 메모리의 주소라고 가정합니다.

스택 주소 지정은 명령에 주소가 포함되어 있지 않다고 가정합니다. 16비트 SP 레지스터(스택 포인터)의 내용으로 메모리 셀에 주소 지정.

명령 시스템

MP 명령 시스템은 MP가 수행할 수 있는 기본 작업의 전체 목록입니다. 이러한 명령으로 제어되는 MP는 기본 산술 및 논리 연산, 데이터 전송, 두 값 비교 등과 같은 간단한 작업을 수행합니다. MP KR580VM80의 ​​명령 수는 78개(수정 244개 포함)입니다.

다음과 같은 명령 그룹이 있습니다.

데이터 전송

산수;

브레인 티저;

점프 명령;

입력-출력 명령, 스택 제어 및 작업.


명령을 설명하고 프로그램을 작성하는 데 사용되는 기호 및 약어

상징 절감
주소 16비트 주소
데이터 8비트 데이터
데이터 16 16비트 데이터
포트 8비트 I/O 주소(I/O 장치)
바이트 2 두 번째 명령 바이트
바이트 3 세 번째 명령 바이트
R, R1, R2 레지스터 중 하나: A, B, C, D, E, H, L
RP 레지스터 쌍 중 하나: B - 항공기 쌍을 설정합니다. D - 한 쌍의 DE를 설정합니다. H - HL 쌍 지정
RH 쌍의 첫 번째 레지스터
RL 쌍의 두 번째 레지스터
Λ 부울 곱셈
V 부울 추가
모듈로 2 덧셈
주소가 HL 레지스터 쌍의 내용을 지정하는 메모리 셀, 즉 M = (HL)



맨 위