Лекция: Объектный код компилятора C0

 

Объектный код, т. е. результат трансляции С0-программы, представляет собой программу на языке ассемблера IBM PC, состоящую из сегмента кода (команд), сегмента данных и сегмента стека. Сегмент данных содержит области для хранения значений глобальных переменных С0-программы, создаваемые псевдокомандами вида:

_имя DW ?

Локальные переменные и параметры каждой функции С0-программы хранятся в сегменте стека в виде кадра, структура которого показана на рис. 1. Адрес кадра находится в регистре ВР. На рис. 2 показан кадр стека функции kod.

В отличие от глобальных переменных, адреса которых в ассемблерной программе задаются их именами, адреса локальных переменных задаются с помощью смещений относительно регистра ВР в виде:

смещeние [BP].

В этом случае в объектной программе «Коды символов» адресом переменной с является ее имя, а адрес переменной (параметра) x запишется как 6[ВР].

Сегмент команд состоит из процедур на языке ассемблера. Каждая процедура соответствует одной функции С0-программы и имеет такое же имя (перед ним вставляется подчеркивание). Процедуры размещены в таком же порядке, как функции С0-программы.

 

 
 

Локальная переменная k

 
 

-4 .. .

 
 

-2 Локальная переменная 1

 
 

BP Адрес предыдущего кадра -2 Значение y

 
 

2 Адрес возврата BP 0 Адрес предыд. кадра

 
 

4 Параметр n 2 Адрес возврата

 
 

.. . 4 Значение baza

Параметр 1 6 Значение x

 

       
 
   

Рис. 1. Кадр стека Рис. 2. Кадр стека

функции kod

Пример 2. Структура объектной программы для примера 1:

ASSUME CS:KOM_,SS:STEK_,DS:DAN_

; Сегмент стека

STEK_ SEGMENT STACK

DW 10000 DUP (?); Область памяти для стека

DNOST_ DW ?

STEK_ ENDS

; Сегмент команд

KOM_ SEGMENT

_kod PROC ;

.. .; Объектный код функции kod

_kod ENDP ;

_main PROC ;

.. .; Объектный код функции main

_main ENDP ;

INCLUDE std.asm; Процедуры библиотечных функций

KOM_ ENDS

; Сегмент данных

DAN_ SEGMENT

_c DW?; Область для значения глобальной переменной c

DAN_ ENDS

END _main; Адрес точки входа в программу

; Компилятоp С0 от 10/04/08;

; колич. ошибок 0

Структура обычной процедуры (не main):

_имя PROC

; Пролог процедуры (создание кадра стека)

PUSH BP; Сохранение регистра BP

MOV BP,SP; Адрес кадра стека

[ SUB SP,2*кол.лок.переменных; Создание лок-х пер-х]

; Объектный код операторов функции

.. .

; Объектный код оператора return; обычной функции (не main)

[ ADD SP,2*кол.лок.перем-х; Удаление локальных пер-х ]

POP BP; Восстановление регистра BP

RET 2*кол.параметров; Удаление параметров и возврат

_имя ENDP

Команда PUSH сохраняет значение регистра BP в стеке, MOV пересылает адрес кадра стека в регистр BP, SUB выделяет в кадре стека место для локальных переменных.

Команда ADD удаляет из стека локальные переменные, РОР восстанавливает в регистре BP адрес кадра вызывающей функции, RET удаляет из стека параметры функции и выполняет возврат.

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

 

MOV AH,4CH

INT 21H

 

Они обеспечивает выход в операционную систему с помощью функции 4СН прерывания номер 21H (типа 21Н).

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

Структура процедуры main:

_main PROC FAR

MOV AX,DAN_; Адрес сегмента данных--> регистр DS

MOV DS,AX ;

MOV AX,STEK_; Адрес сегмента стека --> регистр SS

MOV SS,AX ;

LEA SP,DNOST_; Адрес дна стека

; Пролог процедуры (создание кадра стека)

.. .

; Объектный код операторов функции main

.. .

; Объектный код оператора return; функции main

[ ADD SP,2*кол.лок.перем-х; Удаление локальных пер-х ]

POP BP; Восстановление регистра BP

MOV AH,4CH; Выход в MS DOS

INT 21H ;

_main ENDP

 

Обозначим объектный код некоторой конструкции С0-программы как

объект_код (конструкция).

Ниже в обобщенном виде приведена форма объектного кода разных видов операторов языка С0, которые записаны перед своим объектным кодом в виде комментария языка ассемблера (как в выходном файле компилятора С0).

; выражение;

объект_код (выражение)

; { оператор_1; оператор_2;… оператор_n; }

объект_код (оператор_1)

объект_код (оператор_2)

.. .

объект_код (оператор_n)

; return выражение;

объект_код (выражение)

ADD SP,2*кол.лок.переменных

POP BP

RET 2*кол.параметров

; if (выражение) оператор

объект_код (выражение)

РОР AX; значение выражения

TEST AX,AX; проверка значения

JNZ CC_i; истина (не нуль)

JMP CC_i+1; обход оператора

СС_i:

объект_код (оператор)

СС_i+1:

; while (выражение) оператор

СС_i:

объект_код (выражение)

РОР AX; значение выражения

TEST AX,AX; проверка значения

JNZ CC_i+1; истина

JMP CC_i+2; выход из цикла

CC_i+1:

объект_код (оператор); тело цикла

JMP CС_i; переход на начало цикла

CC_i+2:

Для организации ветвлений и циклов компилятор вставляет в объектную программу метки вида СС_1, СС_2и т. д., которые здесь обозначены как СС_i. Чтобы вставляемые транслятором метки не могли совпасть с именами функций или глобальных переменных С0-программы, транслятор добавляет к меткам символ подчеркивания “_”, который в языке ассемблера используется наравне с буквами. Этот прием называется декорированием имен. Имена функций и глобальных переменных, в свою очередь, приходится декорировать, чтобы они не совпали с именами сегментов, регистров или команд языка ассемблера.

В объектном коде операторов if и while пару соседних команд перехода нельзя заменить одной командой с противоположным условием, так как в IBM PC условный переход возможен лишь на расстояние не более 128 байтов. Если объект_код (оператор) занимает более 128 байт, возникнет ошибка. В отличие от условного перехода, безусловный переход возможен на любое расстояние.

Объектный код выражения состоит из групп команд, реализующих операции выражения в порядке их выполнения. Результат каждой операции (в том числе значение функции) и значение выражения помещаются в регистр AX.

Если выражение заключено в скобки, например, условие в операторах if и while или выражение-параметр в вызове функции, его значение затем помещается в стек.

Выражение из одного операнда (без операций) – переменная или константа, переводится в команду вида:

MOV AX, константа

илиMOV AX, адрес-переменной

 

Если операндами являются константы (числа), то операция выполняется транслятором, заменяется результатом и не появляется в объектном коде, например, объектный код выражения 8 / 2 + X совпадает с объектным кодом выражения 4 + X.

Объектный код операции состоит из следующих шагов.

1. Загрузка 2-го операнда в регистр BX (для присваивания и изменения знака вместо BX используется AX).

2. Загрузка 1-го операнда в регистр AX. (кроме присваивания и изменения знака).

3. Выполнение операции над AX и BX с записью результата в AX (остаток от деления получается в DX). Функции возвращают значение в регистре AX.

4. Если операция не является последней в выражении, то ее результат помещается в стек.

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

Операция, операнды которой являются константами, не компилируется, а интерпретируется, т. е. выполняется транслятором, например, операторы

X=Y+2*5; и X=Y+10; имеют одинаковый объектный код.

Объектный код 3-го шага в зависимости от операции имеет следующий вид.

Присваивание = :

 

MOV адрес-переменной,AX

Операции сравнения ( == != < > <= >= ):

 

CMP AX,BX

MOV AX,1

усл-переход CC_i

SUB AX,AX

CC_i:

 

Команда условного перехода вставляется в зависимости от использованной операции сравнения.

Операция: == != < > <= >=

усл-переход: JE JNE JL JG JLE JGE

Арифметические операции:

 

+: ADD AX,BX; сложение

— : SUB AX,BX; вычитание

— : NEG AX; изменение знака

*: IMUL BX; умножение

/ или % :

CWD; преобразование делимого в 4 байта

IDIV BX; деление

Для операции %, если она последняя в выражении, добавляется команда:

MOV AX,DX

Вызов функции имя-функции (выражение_1,…, выражение_n) :

 

объект_код (выражение_1); параметр_1 --> стек

.. .

объект_код (выражение_n); параметр_n --> стек

CALL имя-функции

 

Для ассемблирования необходимо наличие библиотеки стандартных функций — файла std.asm, который присоединяется командой INCLUDE к транслируемой программе на этапе ее ассемблирования (приложение 1). Эта команда вставляется компилятором С0 в конце сегмента кода.

Для наглядности результата трансляции компилятор C0 переносит строки исходной программы в получаемую из нее ассемблерную программу в виде строк комментария, начинающихся символом ";". За каждой такой строкой размещается объектный код, т.е. команды, полученные в результате ее трансляции (точнее — после ее ввода).

Сообщения об ошибках в исходной программе также вставляются компилятором С0 в объектный код в виде строк комментария, содержащего номер (тип) ошибки и символ "^", указывающий на текущую позицию предшествующей исходной строки в момент обнаружения ошибки. В конце объектной программы вставляется итоговое сообщение о количестве обнаруженных ошибок, дублируемое на экране.

Программа 2. Ниже приведена объектная программа для С0-программы «Коды символов» (выведена в две колонки). Два последних оператора этой программы не приведены, т. к. практически совпадают с предыдущими двумя операторами и имеют аналогичный объектный код.

 

ASSUME CS:KOM_,SS:STEK_,DS:DAN_ STEK_ SEGMENT STACK DW 100 DUP (?) DNOST_ DW? STEK_ ENDS ;kod (x,baza) KOM_ SEGMENT ;{ int y;; if ((y = x/baza)!= 0) _kod PROC PUSH BP MOV BP,SP SUB SP,2 MOV BX,4[BP] MOV AX,6[BP] CWD IDIV BX MOV -2[BP],AX PUSH AX MOV BX,0 POP AX CMP AX,BX MOV AX,1 JNE CC_1 SUB AX,AX CC_1:; kod (y, baza); TEST AX,AX JNZ CC_3 JMP CC_2 CC_3: MOV AX,-2[BP] PUSH AX MOV AX,4[BP] PUSH AX CALL _kod; putchar (x%baza + 48); CC_2: MOV BX,4[BP] MOV AX,6[BP] CWD IDIV BX PUSH DX MOV BX,48 POP AX ADD AX,BX PUSH AX ;} CALL _putchar ADD SP,2 POP BP RET 4 ;int c; ;main () _kod ENDP _main PROC FAR MOV AX,DAN_ MOV DS,AX MOV AX,STEK_ MOV SS,AX ;{ c=0; LEA SP,DNOST_ PUSH BP MOV BP,SP MOV AX,0; while (c != 13) MOV _c,AX CC_4: MOV BX,13 MOV AX,_c CMP AX,BX MOV AX,1 JNE CC_6 SUB AX,AX CC_6:; { c = getchar (); TEST AX,AX JNZ CC_7 JMP CC_5 CC_7: CALL _getchar; putchar (61); MOV _c,AX MOV AX,61 PUSH AX; kod (c, 10); CALL _putchar MOV AX,_c PUSH AX MOV AX,10 PUSH AX; } CALL _kod JMP CC_4 ;} CC_5: POP BP MOV AH,4CH INT 21H; _main ENDP INCLUDE std.asm KOM_ ENDS DAN_ SEGMENT _c DW? DAN_ ENDS END _main; Компилятоp С0 от 10/04/08:; колич. ошибок 0
еще рефераты
Еще работы по информатике