Остаток от деления ассемблер: Решение: Как вывести остаток от деления
.model tiny | |
.code | |
org 100h | |
pole equ 8 | |
begin: | |
mov ah,9h ;функция 9 Выдать строку на дисплей | |
lea dx,mess ;сообщение DS:DX | |
int 21h | |
mov ah,1 ;функция 1 Ввод с клавиатуры AL=вывод | |
int 21h ;в регистре AL — введеная перемнная | |
mov x,al ;x=AL | |
xor cx,cx ;CX=CX-CX | |
mov cl,al ;CL=AL | |
sub cl,30h ;CL=CL-30h в регистре CL число(преобразуем в число) | |
mov dl,cl ;DL=CL запомнили число(преобразованное число=DL) | |
mov ax,01h ;AX=1 подготовка к вычислению факториала | |
mov bl,01h ;BL=1 AX=1 Dl=Число Cl=Число X=символ числа | |
cloop: | |
mul bl ;AX=BL*AX | |
inc bl ;BL=BL+1 | |
loop cloop ;goto CLOOP when CX>0 | |
;цикл повторяется CX | |
;в CL находится число | |
;CL это младший регистр CX | |
;CX=00[CL] | |
;в регистре AX факториал | |
;преобразование числа в регистре AX в цепочку цифр | |
lea si,z+pole-1 ;SI=[8 dup(‘ ‘)]-1 | |
mov bx,0ah ;BX=Ah делить 2 байтовый | |
nach: | |
;xor dx,dx ;dx=0 очищаем регистр перед делением | |
div bx ;AX=DX:AX/BX DX=ОСТАТОК | |
;если dx=2030h ax=0040h DX:AX=20300040h | |
;DX:AX значение DWORD | |
;ПОЭТОМУ НАДО ОБНУЛЯТЬ DX перед делением | |
cmp ax,0 ;ax-0 | |
;проверка результата деления, если число | |
;однозначное то на выход | |
;если больше двух знаков продолжать деление | |
je kon ;if ax=0 goto kon; je=jz | |
add dl,30h ;dl=dl+30h dl становится символом | |
;dl это младший регистр dx | |
;dx=остаток от деления | |
;dl=остаток от деления в виде бита | |
mov [si],dl ;[si]=dl [si]=z+pole-1 | |
;пересылка символа dl В КОНЕЦ СТРОКИ | |
;si=адрес текущего конца строки | |
dec si ;si=si-1. | |
;Уменьшаем адрес конца строки на единицу | |
jmp nach ;GOTO nach | |
kon: | |
;В регистре SI колличество цифр в результата | |
add dl,30h ;код цифр старшего разряда | |
mov [si],dl ;переслали введеную цифру в поле ввода | |
;вывод на экран | |
mov ah,9 ;Функция 9 Выдать строку на дисплей | |
lea dx,ans ;Адрес начала строки. Выводится всё по порядку до знака $. | |
int 21h | |
ret | |
mess db «Введите число <=9:»,0dh,0ah,»$» | |
ans db 0dh,0ah, «Факториал « | |
x db ?,» равен « | |
z db Pole dup (‘ ‘) ;поле вывода | |
db 0dh,0ah ,’$’ | |
end begin |
Ассемблер: Эксперимент 10 Программирование по материалу — 2. Решаем проблему переполнения деления
При делении на div может произойти переполнение. . Из-за этой проблемы обратите внимание на значения делителя и делимого при выполнении операций деления.Например, 1000000/10 нельзя вычислить с помощью инструкции div.. Так что делать? Мы используем следующиеПодпрограмма divdw solution
Описание подпрограммы
Имя: divdw
Функция: выполнение операции деления без переполнения.Делимое — двойное слово, делитель — слово, а результат — двойное слово.
Параметры: (ax) = младшие 16 бит данных типа двойное слово
(Dx) = старшие 16 бит данных двойного слова
(Cx) = делитель
Возврат: (dx) = старшие 16 бит результата, (ax) = младшие 16 бит результата
(Cx) = остаток
Формула подсказки приведена в книге:X/N = int(H/N)*65536+[rem(H/N)*65536+L]/N, Что это означает? Поначалу блогер тоже растерялся.
На самом деле в книге говоритсяint (H / N) означает частное H / N, и его можно упаковать в 16-битный коммерческий формат, тогдаInt (H / N) * 65536, что не является настоящим общим частным * 65536,65536 = 2 ^ 16, что означаетСдвиньте частное влево на 16 бит, частное H / N — это старшие 16 бит результата X / N!
Что означает [rem (H / N) * 65536 + L] / N?rem (H / N) представляет собой остаток от H / N, а затем сдвигается вправо на 16 бит и помещает младшие 16 бит исходных данных в младшие биты,Составляет 32-битное делимое! из-заint(H/N)*65536Это определенно целое число без остаткаСтаршие 16 бит результата X / N, ПотомМладшие 16 бит и остаток результата генерируются в виде [rem (H / N) * 65536 + L] / N !Результат второй половины деления используется как младшие 16 бит X / N, а остаток используется как остаток от X / N. 。
; Эксперимент 10 Задача 2 Решить проблему переполнения деления
; Переполнение деления может произойти, когда для деления используется div. Из-за этой проблемы обратите внимание на значение делителя и дивиденда при выполнении операций деления.
; Например, 1000000/10 нельзя вычислить с помощью инструкции div. Так что делать? Мы используем следующую подпрограмму divdw для решения.
assume cs:code
code segment
start:
mov ax,4240h
mov dx,000fh
mov cx,0ah
call divdw
mov ax,4c00h
int 21h
; Имя: divdw
; Функция: выполнение операции деления без переполнения, делимое - тип двойное слово, делитель - тип слова, а результат - тип двойное слово.
; Параметр: (ax) = младшие 16 бит данных типа двойное слово
; (Dx) = старшие 16 бит данных типа двойное слово
; (Cx) = делитель
; Возврат: (dx) = старшие 16 бит результата, (ax) = младшие 16 бит результата
; (Cx) = остаток
; Основная формула X / N = INT (H / N) * 65536 + [REM (H / N) * 65536 + L] / N
; X: делимое, N (cx): делитель, H (dx): старшие 16 бит X, L (ax): младшие 16 бит X
divdw:
push bx; регистра недостаточно, используйте bx
push ax; временно сохранить младшие 16 бит (L)
; Вычислить INT (H / N) * 65536 32 бита, разделенные на 16 бит, частное 16 бит, сохраненное в AX, является старшими 16 битами всего результата X / N, а оставшиеся 16 бит - как [REM (H / N) * в DX 65536 + L] старшие 16 бит
mov ax,dx
mov dx,0
div cx
mov bx, ax; не может быть напрямую помещен в dx, dx будет использоваться позже
; Вычислить [REM (H / N) * 65536 + L] / N, 16-битное частное сохраняется в AX, который оказывается младшим битом результата X / N, а оставшиеся 16 бит помещаются в DX -> помещается в CX
pop ax; восстанавливаются младшие 16 бит делимого (L), которые являются младшими 16 битами [REM (H / N) * 65536 + L]
div cx
mov cx, dx; 16 бит остатка положить -> CX
mov dx, bx; помещаем старшие 16 бит результата в -> DX
pop bx; восстановить bx
ret
code ends
end start
Assembler: 45. Арифметические команды сопроцессора
Данная группа команд реализует четыре основные арифметические операции – сложение, вычитание, умножение и деление. С точки зрения типов операндов, арифметические команды можно разделить на работающие с целыми и вещественными операндами.
Арифметические команды имеют следующий формат Fppp (для вещественных операндов) или FIppp (для целочисленных операндов), где ррр может принимать значения:
- ADD – сложение
- SUB – вычитание
- SUBR – обратное вычитание
- MUL – умножение
- DIV – деление
- DIVR – обратное деление
Возможны следующие комбинации операндов:
Fppp (FIppp) — выполняет операцию над ST(0) — приемник и ST(1) — источник. Результат заносится в регистр стека сопроцессора ST(0).
Fppp (FIppp) — выполняет операцию над значением ST(0) и источником. Результат заносится в регистр стека сопроцессора ST(0).
Fppp (FIppp) , — выполняет операцию над значением в регистре стека сопроцессора ST(i) и значением в вершине стека ST(0). Результат заносится в регистр ST(i).
FpppP (FIpppР) , — операция выполняется аналогично предыдущей команде, только последним действием команды является выталкивание значения из вершины стека сопроцессора ST(0). Результат сложения остается в регистре ST(i-1).
В чем заключается «обратность» вычитания и деления?
Проанализируйте описание этих двух команд и Вам все станет понятно:
FSUB st(i), st — команда вычитает значение в вершине стека SТ(0) из значения в регистре стека сопроцессора ST(i). Результат вычитания запоминается в регистре стека сопроцессора ST(i).
FSUBR st(i),st — команда вычитает значение в вершине стека ST(0) из значения в регистре стека сопроцессора ST(i). Результат вычитания запоминается в вершине стека сопроцессора — регистре ST(0).
Пример: сложение трех чисел: .data Sarray dd 1.5, 3.4, 6.6 ;объявим массив вещественных чисел, котрые мы хотим сложить Sum dd ? ;зарезервируем место для результата .code Finit ;инициализируем сопроцессор Fld Sarray ;загрузим первый элемент Sarray Fadd Sarray+4 ;прибавим к вершине второй элемнт массива Fadd Sarray+8 ;и третий туда же Fstp Sum ;выгрузим значение из вершины стека сопроцессора в переменную Sum
Дополнительные арифметические команды
- FSQRT ; извлечение квадратного корня
- FSCALE ; масштабирование ST(0) = ST(0)*2ST(1), ST(1) – целое число
- FPREM ; вычисляет частичный остаток ST(0) = ST(0) — q*ST(1), где q – целая часть результата ST(0)/ST(1)
- FPREM1 ; вычисляет частичный остаток ST(0) = ST(0) — q*ST(1), где q – ближайшее к ST(0)/ST(1) целое число
- FPNDINT ; округление до целого
- FXTRACT ; расцепляет число на — порядок, который заменяет число в ST(1), мантиссу, которая помещается в ST(0)
- FABS ; получение модуля числа
- FCHS ; изменение знака числа
imul (ошибка в программе) [asm] : Низкоуровневое программирование
%TITLE «Ваш комментарий программы»
INCLUDE IO.ASM
MODEL small
ST1 SEGMENT ;Описали сегмент стека;
DB 128 DUP(?)
ST1 ENDS
DATA SEGMENT
A DB ‘Целая часть:’,’$’
B DB ‘Остаток:’,’$’
C DB ‘Деление на ноль!’,’$’
DATA ENDS
CODE SEGMENT ;открыли сегмент кода;
ASSUME SS:ST1,DS:DATA,CS:CODE ;связали регистровые сегменты с сегментами;
Start:
push ds
sub ax, ax
push ax
mov ax, data
mov ds, ax
;========== Ниже пишите Ваш код ==============================
MOV DI,1 ;переменная знака
MOV CX,0 ;целая часть
inint DX ;ввод делимого
inint BX ;ввод делителя
CMP BX,0 ;оцениваем делитель
JG L3 ;делитель положительный, переходим к оценке делимого
JE ER ;делитель ноль — ошибка
NOT BX ;берем bx по модулю
ADD BX,1
NOT DI ;учитываем минус делителя
ADD DI,1
L3: CMP DX,0 ;оцениваем делимое
JG L5 ;делимое положительное, переходим к делению
JE L4 ;делимое ноль, переходим к быстрому выводу, где целая часть 0, остаток — bx
NOT DX ;берем dx по модулю
ADD DX,1
NOT DI ;учитываем минус делимого
ADD DI,1
L5: CMP dx, bx ;проверяем ax<bx но они не равны нулю
JB L4 ;переходим к быстрому выводу, где целая часть 0, а остаток — bx
L1: CMP DX,BX ;отнимаем-отнимаем-…
JB L2
SUB DX,BX ;отняли..
INC CX ;..к целой части 1 прибавили
JMP L1 ;и опять сначала
ER: MOV AH,9H
LEA DX,C
INT 21H
JMP THEEND
L4: MOV AH,9H ;случай когда целая часть ноль, а остаток — это bx
LEA DX,A
INT 21H
OUTINT CX
NEWLINE
MOV AH,9H
LEA DX,B
INT 21H
OUTINT BX
JMP THEEND
L2:
outint dx
outint di
MOV AX,CX ;в ax целая часть без учета знака, ax умножится на знак
IMUL DI ;di умножится на ax -> ax, это конечный результат целой части
OUTINT AX
OUTINT DX
OUTINT DI
MOV DI,AX
MOV BX,DX
MOV AH,9H
LEA DX,A
INT 21H
OUTINT DI ;DI-целая часть
NEWLINE
MOV AH,9H
LEA DX,B
INT 21H
OUTINT BX ;BX-остаток
JMP THEEND
THEEND:
;========== Заканчивайте писать Ваш код======================
pop ax
pop ds
Exit: finish
ENDS
END Start
Ассемблер i8080 proccessor. Разделение двух чисел 16 бит
Разделение программного обеспечения является медленным (или сложным). Оборудование для этого обычно требует большего пространства или времени. Биполярные интегрированные технологии фактически реализовали полностью комбинаторный разрыв FP в оборудовании … еще в тот же день. Но такие подвиги часто делаются не так.
У вас уже есть основные замечания о подразделении, которые будут применяться практически всеми, кто пытается их использовать. Но они медленнее, чем им нужно. Даже на 8080А. (Я на самом деле все еще владею несколькими из них и их поддержкой, чипами. И у моего ближайшего друга все еще есть его оригинальный Altair 8800, который довольно хорош.)
Не так давно я участвовал в совершенствовании библиотеки с плавающей запятой для коммерческого компилятора для чипа MSP430. Я смог резко улучшить производительность, применив так называемое «невосстанавливающее подразделение» и применив некоторые новые идеи сборки к дизайну. В то время никакой другой коммерческий компилятор не мог достичь своей скорости. Оказывается, я написал небольшую документацию о процессе, который я применил в комментариях, и я поделюсь с вами здесь:
; This routine uses non-restoring division. If you aren't familiar with it,
; consider this idea:
;
; Call each step of the trial subtraction T[n]. At each step we want to test
; the result of 2 times the prior remainder minus the divisor. If the trial
; subtraction succeeds, we just shift the remainder one bit to the left and
; do the subtraction again. So at each step our successful trial subtraction
; it is something like this: ... T[i]=2*T[i-1]-D, T[i+1]=2*T[i]-D ... and so
; on. But if the trial subtraction fails, the divisor needs to added back
; to the remainder before before shifting and doing the next subtraction.
; Instead, this is T[i+1]=2*(T[i]+D)-D. But this is just T[i+1]=2*T[i]+D.
; Comparing these two results, you can see that the shift of T[i] still takes
; place, but that in this case addition of the divisor is used on the next
; step instead of subtraction. Non-restoring division is named that way
; because it replaces the addition+shift+subtraction used when subtraction
; from the remainder fails, with shift+addition. It alternates between
; shift+subtract and shift+add, depending on the quotient bit generated.
;
; The division loop is not unrolled here.
;
; This code needs to produce 24 good mantissa bits as a quotient, where the
; leading bit is '1', and we then need to also produce one final bit for
; rounding purposes. (If the leading bit -- the most significant one --
; isn't a '1', then we'd lose significance because of the fixed count of
; generated quotient bits.)
;
; The actual division code loop is best examined as a coroutine. Imagine
; the division routine something like the following diagram. Since program
; text is usually viewed under fixed-point fonts, it should render as a
; readable picture. I apologize for any difficulties in interpreting it:
;
; start
; |
; v
; ,-------,
; |frstbit|
; '-------' ,-------,
; ,-----> | | |
; | v v |
; | ,-------, ,-------, |
; | | sub | | add | |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | | rlc | | rla | |
; | '-------' '-------' |
; | | | |
; | v v |
; | ,-------, ,-------, |
; ''
; z=0 '-------' '-------' z=0
; | z=1 z=1 |
; v v
; ,-------, ,-------,
; | round1| | round0|
; '-------' '-------'
; | |
; v v
; '-------------> end
Вышеупомянутый код не «разворачивается». Это всего лишь один цикл. Вы запускаете его для того, сколько бит требуется.
Суть этого кода состоит в том, чтобы избежать выполнения «добавления назад», если вычитание приводит к отрицательному результату. Вместо этого, деление просто переключает передачи и продолжает идти по другому пути, вместо этого переходит на «другой путь» на некоторое время. Он просто отслеживает, на какой стороне прохода он включен и сдвигается, когда изменяется предположение. Вы можете сделать это и вручную, и вы увидите, что он работает.
Приведенные выше (и ниже) примеры требуют, чтобы идея «нормализации» уже имела место. Это означает, что ведущий бит дивиденда и делителя должен быть равен «1», и вы отслеживаете количество сдвигов, необходимых для начала. Это гарантирует получение полной точности. Но такая инициализация не требуется в невосстанавливающем подразделении. Тот же алгоритм работает, даже если этого не произошло.
Во-первых, я предпочитаю выполнять деление как неподписанное. (Я, конечно, фиксирую знаки).
Я часто использую дивиденд, который в два раза больше размера делителя, где алгоритм создает отдельный фактор и остаток, который имеет тот же размер, что и делитель. Так, например, у меня может быть 48-битный дивиденд и 24-разрядный делитель, коэффициент и остаток. Это едва ли больше кода или времени выполнения, чем для того, чтобы заставить дивиденд быть одного размера. И я получаю более полные результаты. Поэтому я обычно так делаю. Но не всегда. Это зависит.
Вот пример кода, который разворачивается по-восьми. Это намного быстрее, так как счетный контроль выполняется не так часто. Но компромисс — это кодовое пространство. Но когда вам действительно нужна скорость, это очень помогает:
; If you aren't familiar with non-restoring division, the consider this idea:
; Call each step of the trial subtraction T[n]. At each step we want to test
; the result of 2 times the prior remainder minus the divisor. If the trial
; subtraction succeeds, we just shift the remainder one bit to the left and
; do the subtraction again. So at each step our successful trial subtraction
; it is something like this: ... T[i]=2*T[i-1]-D, T[i+1]=2*T[i]-D ... and so
; on. But if the trial subtraction fails, the divisor needs to added back
; to the remainder before before shifting and doing the next subtraction.
; Instead, this is T[i+1]=2*(T[i]+D)-D. But this is just T[i+1]=2*T[i]+D.
; Comparing these two results, you can see that the shift of T[i] still takes
; place, but that in this case addition of the divisor is used on the next
; step instead of subtraction. Non-restoring division is named that way
; because it replaces the addition+shift+subtraction used when subtraction
; from the remainder fails, with shift+addition. It alternates between
; shift+subtract and shift+add, depending on the quotient bit generated.
;
; It is unrolled-by-8 in the sense that the code for generating each bit is
; copied 8 times in inline fashion, to avoid a conditional loop on each bit.
; Since a decrement and conditional jump require three cycles, doing that
; once for 8 bits is a big win over doing it once for each bit.
;
; This code needs to produce 24 good mantissa bits as a quotient, where the
; leading bit is '1', and we then need to also produce one final bit for
; rounding purposes. (If the leading bit -- the most significant one --
; isn't a '1', then we'd lose significance because of the fixed count of
; generated quotient bits.)
;
; The actual division code loop is best examined as a coroutine. Imagine
; the division routine something like the following diagram. Since program
; text is usually viewed under fixed-point fonts, it should render as a
; readable picture. I apologize for any difficulties in interpreting it:
;
; start ,-------, ,-------,
; | | | | |
; | | v v |
; | | ,-------, ,-------, |
; v | |movbyte| |movbyte| |
; ,-------, | '-------' '-------' |
; |frstbit| | | | |
; '-------' | v v |
; | | ,-------, ,-------, |
; | | |rlc/sub| |rla/add| |
; v | '-------'----------, ,----------'-------' |
; '------ | ----> | c=0 \/ c=1 | c=0 |
; | c=1 v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; | |rlc/sub| |rla/add| |
; | '-------'----------, ,----------'-------' |
; | c=1 | c=0 \/ c=1 | c=0 |
; | v /\ v |
; | ,-------, ,-------, |
; ''
; z=0 '-------' '-------' z=0
; | z=1 z=1 |
; v v
; ,-------, ,-------,
; | round1| | round0|
; '-------' '-------'
; | |
; v v
; '-------------> end
Ну, вот и все. Если у вас есть какие-либо вопросы по поводу процесса, спросите. Я сделал много 8080 сборки кодирования. Но прошло уже несколько десятилетий, так что несите меня, если я кажусь немного ржавым.
59 (Вопросы по разным темам с ответами (программирование)) — документ, страница 2
слово 2 слово 2
слово 2 слово 1
слово 1 слово 2
слово 1 слово 1
Каждое произведение в регистрах DX и AX складывается с соответствующим словом в окончательном результате.
Хотя логика умножения двойных слов аналогична умножению двойного слова на слово, имеется одна особенность, после пары команд сложения ADD/ADC используется еще одна команда ADC, которая прибавляет 0 к значению в итоговом поле.
Это необходимо потому, что первая команда ADC сама может вызвать перенос, который последующие команды могут стереть. Поэтому вторая команда ADC прибавит 0, если переноса нет, и прибавит 1, если перенос есть.
Финальная пара команд ADD/ADC не требует дополнительной команды ADC, так как область итога достаточно велика для генерации окончательного результата и переноса на последнем этапе не будет.
Сдвиг регистровой пары DX:AX
Следующая подпрограмма может быть полезна для сдвига содержимого pегистровой пары DX:AX вправо или влево. Можно придумать более эффективный метод, но данный пример представляет общий подход для любого числа циклов (и, соответственно, сдвигов) в регистре CX. Заметьте, что сдвиг единичного бита за разрядную сетку устанавливает флаг переноса.
Сдвиг влево на 4 бита
MOV CX,04 ;Инициализация на 4 цикла C20:
SHL DX,1 ;Сдвинуть DX на 1 бит влево
SHL AX,1 ;Сдвинуть AX на 1 бит влево
ADC DX,00 ;Прибавить значение переноса
LOOP C20 ;Повторить Сдвиг вправо на 4 бита
MOV CX,04 ;Инициализация на 4 цикла D20:
SHR AX,1 ;Сдвинуть AX на 1 бит вправо
SHR DX,1 ;Сдвинуть DX на 1 бит вправо
JNC D30 ;В случае, если есть перенос,
OR AH,10000000B ; то вставить 1 в AH D30:
LOOP D20 ;Повторить
Ниже приведен более эффективный способ для сдвига влево, не требующий организации цикла. В этом примере фактор сдвига записывается в регистр CL.
Пример написан для сдвига на 4 бита, но может быть адаптирован для других величин сдвигов:
MOV CL,04 ;Установить фактор сдвига
SHL DX,CL ;Сдвинуть DX влево на 4 бита
MOV BL,AH ;Сохранить AH в BL
SHL AX,CL ;Сдвинуть AX влево на 4 бита
SHL BL,CL ;Сдвинуть BL вправо на 4 бита
OR DL,BL ;Записать 4 бита из BL в DL
Деление
Операция деления для беззнаковых данных выполняется командой DIV, a для знаковых — IDIV. Ответственность за подбор подходящей команды лежит на программисте.
Существуют две основные операции деления:
Деление слова на байт
Делимое находится в регистре AX, а делитель — в байте памяти или а однобайтовом регистре. После деления остаток получается в регистре AH, а частное — в AL. Так как однобайтовое частное очень мало (максимально +255 (шест.FF) для беззнакового деления и +127 (шест.7F) для знакового), то данная операция имеет ограниченное использование.
Деление двойного слова на слово
Делимое находится в регистровой паре DX:AX, а делитель — в слове памяти или а регистре. После деления остаток получается в регистре DX, а частное в регистре AX. Частное в одном слове допускает максимальное значение +32767 (шест.FFFF) для беззнакового деления и +16383 (шест.7FFF) для знакового.
В единственном операнде команд DIV и IDIV указывается делитель. Рассмотрим следующую команду:
DIV DIVISOR
В случае, если поле DIVISOR определено как байт (DB), то операция предполагает деление слова на байт. В случае, если поле DIVISOR определено как слово (DW), то операция предполагает деление двойного слова на слово.
При делении, например, 13 на 3, получается результат 4 1/3. Частное есть 4, а остаток — 1. Заметим, что ручной калькулятор выдает в этом случае результат 4,333…. Значение содержит целую часть (4) и дробную часть (,333). Значение 1/3 и 333… есть дробные части, в то время как 1 есть остаток от деления.
Беззнаковое деление: Команда DIV
Команда DIV делит беззнаковые числа.
Знаковое деление: Команда IDIV
Команда IDIV (Integer DIVide) выполняет деление знаковых чисел.
Повышение производительности
При делении на степень числа 2 (2, 4, и так далее) более эффективным является сдвиг вправо на требуемое число битов. В следующих примерах предположим, что делимое находится в регистре AX:
Деление на 2:
SHR AX,1
Деление на 8:
MOV CL,3
SHR AX,CL
Переполнения и прерывания
Используя команды DIV и особенно IDIV, очень просто вызвать пеpеполнение. Прерывания приводят (по крайней мере в системе, используемой при тестировании этих программ) к непредсказуемым результатам. В операциях деления предполагается, что частное значительно меньше, чем делимое.
Деление на ноль всегда вызывает прерывание. Но деление на 1 генерирует частное, которое равно делимому, что может также легко вызвать прерывание.
Рекомендуется использовать следующее правило: если делитель — байт, то его значение должно быть меньше, чем левый байт (AH) делителя: если делитель — слово, то его значение должно быть меньше, чем левое слово (DX) делителя.
При использовании команды IDIV необходимо учитывать тот факт, что либо делимое, либо делитель могут быть отрицательными, а так как сравниваются абсолютные значения, то необходимо использовать команду NEG для временного перевода отрицательного значения в положительное.
Деление вычитанием
В случае, если частное слишком велико, то деление можно выполнить с помощью циклического вычитания.
Метод заключается в том, что делитель вычитается из делимого и в этом же цикле частное увеличивается на 1.
Вычитание продолжается, пока делимое остается больше делителя. В cледующем примере, делитель находится в регистре AX, а делимое — в BX, частное вырабатывается в CX:
SUB CX,CX ;Очистка частного C20:
CMP AX,BX ;В случае, если делимое < делителя,
JB C30 ; то выйти
SUB AX,BX ;Вычитание делителя из делимого
INC CX ;Инкремент частного
JMP C20 ;Повторить цикл С30:
RET ;Частное в CX, остаток в AX
В конце подпрограммы регистр CX будет содержать частное, а AX — oстаток. Пример умышленно примитивен для демонстрации данной техники деления. В случае, если частное получается в регистровой паре DX:AX, то необходимо сделать два дополнения:
1. В метке C20 сравнивать AX и BX только при нулевом DX.
2. После команды SUB вставить команду SBB DX,00.
Примечание: очень большое частное и малый делитель могут вызвать тысячи циклов.
Преобразование знака
Команда NEG обеспечивает преобразование знака двоичных чисел из положительного в отрицательное и наоборот. Практически команда NEG устанавливает противоположные значения битов и прибавляет 1. Примеры:
NEG AX
NEG BL
NEG BINAMT ;(байт или слово в памяти)
Преобразование знака для 35-битового (или большего) числа включает больше шагов. Предположим, что регистровая пара DX:AX содержит 32-битовое двоичное число. Так как команда NEG не может обрабатывать два регистра одновременно, то ее использование приведет к неправильному результату. В следующем примере показано использование команды NOT:
NOT DX ;Инвертирование битов
NOT AX ;Инвертирование битов
ADD AX,1 ;Прибавление 1 к AX
ADC DX,0 ;Прибавление переноса к DX
Остается одна незначительная проблема: над числами, представленными в двоичном формате, удобно выполнять арифметические операции, если сами числа определены в программе. Данные, вводимые в программу с дискового файла, могут также иметь двоичный формат. Но данные, вводимые с клавиатуры, представлены в ASCII-формате.
Хотя ASCII-коды удобны для отображения и печати, они требуют специальных преобразований в двоичный формат для арифметических вычислений.
Важно:
u Будьте особенно внимательны при использовании однобайтовых pегистров. Знаковые значения здесь могут быть от -128 до +127.
u Для многословного сложения используйте команду ADC для учета переносов от предыдущих сложений. В случае, если операция выполняется в цикле, то используя команду CLC, установите флаг переноса в 0.
u Используйте команды MUL или DIV для беззнаковых данных и команды IMUL или IDIV для знаковых.
u При делении будьте осторожны с переполнениями. В случае, если нулевой делитель возможен, то обеспечьте проверку этой операции. Кроме того, делитель должен быть больше содержимого регистра AH (для байта) или DX (для слова).
u Для умножения или деления на степень двойки используйте cдвиг. Сдвиг вправо выполняется командой SHR для беззнаковых полей и командой SAR для знаковых полей. Для сдвига влево используются идентичные команды SHL и SAL.
u Будьте внимательны при ассемблировании по умолчанию. Например, если поле FACT определено как байт (DB), то команда MUL FACT полагает множимое в регистре AL, а команда DIV FACT полагает делимое в регистре AX. В случае, если FACT определен как слово (DW), то команда MUL FACT полагает множимое в регистре AX, а команда DIV FACT полагает делимое в регистровой паре DX:AX.
Обработка данных в форматах ASCII и BCD
Для получения высокой производительности компьютер выполняет aрифметические операции над числами в двоичном формате. Этот формат не вызывает особых трудностей, если данные определены в самой программе. Во многих случаях новые данные вводятся программой с клавиатуры в виде ASCII символов в деcятичном формате. Аналогично вывод информации на экран осуществляется в кодах ASCII. Например, число 23 в двоичном представлении выглядит как 00010111 или шест.17; в коде ASCII на каждый cимвол требуется один байт и число 25 в ASCII-коде имеет внутpеннее представление шест.3235.
При программировании на языках высокого уровня для обозначения порядка числа или положения десятичной запятой (точки) можно положиться на компилятор. Однако, компьютер не распознает десятичную запятую (точку) в арифметических полях. Так как двоичные числа не имеют возможности установки десятичной (или двоичной) запятой (точки), то именно программист должен подразумевать и определить порядок обрабатываемых чисел.
ASCII-формат
Данные, вводимые с клавиатуры, имеют ASCII-формат, например, буквы SAM имеют в памяти шестнадцатеричное представление 53414D, цифры 1234 — шест.31323334. Во многих случаях формат алфавитных данных, например, имя человека или описание статьи, не меняется в программе. Но для выполнения арифметических операций над числовыми значениями, такими как шест.31323334, требуется специальная обработка.
С помощью следующих ассемблерных команд можно выполнять арифметические операции непосредственно над числами в ASCII-формате:
AAA (ASCII Adjust for Addition — коррекция для сложения
ASCII-кода)
AAD (ASCII Adjust for Division — коррекция для деления
ASCII-кода)
AAM (ASCII Adjust for Multiplication — коррекция для умножения ASCII-кода)
AAS (ASCII Adjust for Subtraction — коррекция для вычитания
ASCII-кода)
Эти команды кодируются без операндов и выполняют автоматическую коррекцию в регистре AX. Коррекция необходима, так как ASCII-код представляет так называемый распакованный десятичный формат, в то время, как компьютер выполняет арифметические операции в двоичном формате.
Сложение многобайтовых ASCII-чисел требует организации цикла, который выполняет обработку справа налево с учетом переноса.
Вычитание в ASCII-формате
Команда AAS (ASCII Adjust for Subtraction — коррекция для вычитания ASCII-кодов) выполняется aналогично команде AAA. Команда AAS проверяет правую шест. цифру (четыре бита) в регистре AL. В случае, если эта цифра лежит между A и F или флаг AF равен 1, то из регистра AL вычитается 6, а из регистра AH вычитается 1, флаги AF и CF устанавливаются в 1. Во всех случаях команда AAS устанавливает в 0 левую шест.цифру в регистpе AL.
Умножение в ASCII-формате
Команда AAM (ASCII Adjust for Multiplication — коррекция для умножения ASCII-кодов) выполняет корректировку результата умножения ASCII-кодов в регистре AX. Однако, шест. цифры должны быть очищены от троек и полученные данные уже не будут являться действительными ASCII-кодами. Например, число в ASCII-формате 31323334 имеет распакованное десятичное представление 01020304. Кроме этого, надо помнить, что коррекция осуществляется только для одного байта за одно выполнение, поэтому можно умножать только oдно-байтовые поля; для более длинных полей необходима организация цикла.
Команда AAM делит содержимое регистра AL на 10 (шест.0A) и записывает частное в регистр AH, а остаток в AL. Предположим, что в регистре AL содержится шест.35, а в регистре CL — шест.39. Следующие команды умножают содержимое регистра AL на содержимое CL и преобразуют результат в ASCII-формат:
AX: AND CL,0FH ;Преобразовать CL в 09
AND AL,0FH ;Преобразовать AL в 05 0005
MUL CL ;Умножить AL на CL 002D
AAM ;Преобразовать в распак.дес. 0405
OR AX,3030H ;Преобразовать в ASCII-ф-т 3435
Арифметические процедуры на ассемблере [Архив] — Speccy
Просмотр полной версии : Арифметические процедуры на ассемблере
Не подскажет ли многоуважаемый All где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу. В свое время в спектрумовских E-zine часто публиковались процедуры быстрого умножения/деления, перемножения матриц и тому подобного. А интересуют процедуры и попроще, например знаковое сложение/вычитание. В общем подскажите где подобное можно найти. В принципе даже неважно под Z80 или под что-то другое.
http://www.google.com/search?hl=en&safe=off&sa=X&oi=spell&resnum=0&ct=result&cd=1&q=z80+arithmetic+operations&spell=1
—> http://map.tni.nl/sources/external/z80bits.html
ещё много есть док про Техасс Инструментс (калькулятор такой был на z80).
в них очень много чего есть.
и ещё можешь посмотреть в каком-нибудь опенсорсовом компилере C который может генерить код под z80 посмотреть математическую либу (в соседней ветке как раз компилеры обсуждаются)
Не подскажет ли многоуважаемый All где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу. В свое время в спектрумовских E-zine часто публиковались процедуры быстрого умножения/деления, перемножения матриц и тому подобного. А интересуют процедуры и попроще, например знаковое сложение/вычитание. В общем подскажите где подобное можно найти. В принципе даже неважно под Z80 или под что-то другое.
Ссылок на теорию нет. Есть практика. Позаимствовано у Алко. Он в свою очередь тоже у кого-то взял, может чего и своего добавил.
например знаковое сложение/вычитание.
оно выполняется точно так же как и обычное, главное пределы соблюсти, чтоб неперолнения не возникало. т.е. обычным add и sub.
где можно найти информацию по программированию арифметических процедур на ассемблере? Желателен линк на сайт или книгу
http://baze.au.com/misc/z80bits.html
автор: Milos «baze» Bazelides
содержание:
1 Integer Multiplication
* 1.1 Restoring 8-bit * 8-bit Unsigned
* 1.2 Restoring 16-bit * 8-bit Unsigned
* 1.3 Restoring 16-bit * 16-bit Unsigned
* 1.4 Square Table Driven 8-bit * 8-bit Signed
* 1.5 Square Table Driven 6-bit * 6-bit Signed
* 1.6 Logarithmic Table Driven 8-bit * 8-bit Signed
2 Integer Division
* 2.1 Restoring 8-bit / 8-bit Unsigned
* 2.2 Restoring 16-bit / 8-bit Unsigned
* 2.3 Restoring 16-bit / 16-bit Unsigned
* 2.4 Restoring 24-bit / 8-bit Unsigned
* 2.5 Restoring 24-bit / 16-bit Unsigned
* 2.6 Restoring 32-bit / 8-bit Unsigned
3 Integer Square Root
* 3.1 Basic 8-bit Square Root
* 3.2 Basic 16-bit Square Root
* 3.3 Restoring 16-bit Square Root
* 3.4 16-bit Square Table Bisection
4 Random Number Generators
* 4.1 8-bit Random Number Generator
* 4.2 16-bit Random Number Generator
5 Conversions Between Numbers and Strings
* 5.1 16-bit Integer to ASCII (decimal)
* 5.2 16-bit Integer to ASCII (hexadecimal)
* 5.3 Memory dump (hexadecimal)
6 Cyclic Redundancy Checks (CRC)
* 6.1 16-bit CRC-CCITT
* 6.2 Table Driven 16-bit CRC-CCITT
* 6.3 32-bit CRC-32
* 6.4 Table Driven 32-bit CRC-32
Ссылок на теорию нет. Есть практика. Позаимствовано у Алко. Он в свою очередь тоже у кого-то взял, может чего и своего добавил.
Прикольно, math_lib — это мой файл ;). Но процедуры почти все не я писал. И пользовался не всеми.
Знахарь
02.12.2006, 17:32
Вот! значит массы оценили и велосипед не изобретали — остается пользовать
Дмитрий2012
11.05.2017, 20:22
Понадобились процедуры деления и умножения трехбайтовых чисел. На просторах инета нашел необходимые процедуры деления и умножения в журнале ZX FORMAT 7.Попробовал процедуру деления. Она к сожалению она почему-то оказалась не рабочей. С умножением еще не разбирался. В примере делю число 254639H на 00E489H получаем в аккумуляторе 29H а в HL 0C0FCH. Судя по комментариям в коде результат деления должен быть в регистрах A,H,L т.е в A -0 , в HL должно быть 0029H. Может кто посмотрит код и подскажет где ошибка закралась? или поделится готовыми библиотеками деления, умножения трехбайтовых чисел?
Понадобились процедуры деления и умножения трехбайтовых чисел. На просторах инета нашел необходимые процедуры деления и умножения в журнале ZX FORMAT 7.Попробовал процедуру деления. Она к сожалению она почему-то оказалась не рабочей. С умножением еще не разбирался. В примере делю число 254639H на 00E489H получаем в аккумуляторе 29H а в HL 0C0FCH. Судя по комментариям в коде результат деления должен быть в регистрах A,H,L т.е в A -0 , в HL должно быть 0029H. Может кто посмотрит код и подскажет где ошибка закралась? или поделится готовыми библиотеками деления, умножения трехбайтовых чисел?
Может баян:
«Гуртовцев А.Л… Программы для микропроцессоров. [Djv- 2.3M] Справочное пособие. Авторы: Аркадий Лазаревич Гуртовцев, Сергей Викторович Гудыменко.
(Минск: Вышэйшая школа, 1989)
Скан, обработка, формат Djv: Boroda3, 2006″
КРАТКОЕ ОГЛАВЛЕНИЕ:
Предисловие (3).
Условные сокращения (6).
Методологические замечания (8).
1. Программы арифметики с фиксированной запятой (12).
2. Программы арифметики с плавающей запятой (105).
3. Программы преобразования представлений чисел (145).
4. Программы вычисления элементарных функций (176).
5. Программы обработки структур данных (211).
6. Программы системного обеспечения (245).
http://publ.lib.ru/ARCHIVES/G/GURTOVCEV_Arkadiy_Lazarevich/_Gurtovcev_A.L..html
http://publ.lib.ru/ARCHIVES/G/GURTOVCEV_Arkadiy_Lazarevich/Gurtovcev_A.L…_Programmy_dlya_mikroprocessorov.( 1989).[djv-fax].zip
Дмитрий2012, ты хоть подробно напиши что на что делить… 24bit/16bit или 24bit/8 ?
2.4 Restoring 24-bit / 8-bit Unsigned
Input: E:HL = Dividend, D = Divisor, A = 0
Output: E:HL = Quotient, A = Remainder
add hl,hl ; unroll 24 times
rl e ; …
rla ; …
cp d ; …
jr c,$+4 ; …
sub d ; …
inc l ; …
2.5 Restoring 24-bit / 16-bit Unsigned
Input: A:BC = Dividend, DE = Divisor, HL = 0
Output: A:BC = Quotient, HL = Remainder
slia c ; unroll 24 times
rl b ; …
rla ; …
adc hl,hl ; …
sbc hl,de ; …
jr nc,$+4 ; …
add hl,de ; …
dec c ; …
Дмитрий2012
12.05.2017, 17:03
Может баян:
«Гуртовцев А.Л… Программы для микропроцессоров. [Djv- 2.3M] Справочное пособие.
Спасибо за ссылку на интересную книжку,не попадалась мне еще такая.
Дмитрий2012, ты хоть подробно напиши что на что делить… 24bit/16bit или 24bit/8 ?
В идеале нужна функция деления 32bit/24bit В данный момент меня устроила бы и 24bit /24bit
Задача состоит в том, чтобы данные 32bit переменной в которой тикает время в миллисекундах перевести в часы — минуты – секунды — милисек.
думаю делать так:
час = милисек div 3600000
мин = (милисек mod 3600000) div 60000
сек = (милисек mod 60000) div 1000
милисек = милисек mod 1000
сразу же застрял на делении многобайтных чисел:( сам такую процедуру пока не осилю написать, вот и ищу готовую. Что попадаются в инете и журналах не работают. Толи опечатки там есть, то ли я что не так делаю…
blackmirror
12.05.2017, 17:26
Дмитрий2012, на первом шаге можно вычислять (ms/128)/(3600000/128), тогда делить более чем на 16 разрядные числа не придётся. А это время больше нигде не нужно, то может его лучше хранить и увеличивать по компонентам.
shurik-ua
12.05.2017, 17:27
а ассемблер для какого процессора ?
Дмитрий2012
12.05.2017, 17:32
Дмитрий2012, на первом шаге можно вычислять (ms/128)/(3600000/128), тогда делить более чем на 16 разрядные числа не придётся. А это время больше нигде не нужно, то может его лучше хранить и увеличивать по компонентам.
я об этом даже не подумал, спасибо за подсказку. Если ничего с делением 32 битных чисел не выйдет попробую такой вариант.
Ну а на будущее хотелось бы все-равно иметь процедуры деления 32bit чисел.
а ассемблер для какого процессора ?
для Z80
NEO SPECTRUMAN
12.05.2017, 17:44
В идеале нужна функция деления 32bit/24bit В данный момент меня устроила бы и 24bit /24bit
Задача состоит в том, чтобы данные 32bit переменной в которой тикает время в миллисекундах перевести в часы — минуты – секунды — милисек.
можно без деления
4 таблицы по 1.5К (может даже меньше тк младшие 2 байта не могут указывать количество часов)
для каждого байта 32 битного числа
в которых лежит декодированое значения часов минут секунд
(2 байта часы, 1 байт минуты, 1 байт секунды, 2 байта миллисекунды)
потом складываем полученные 4 значения с учетом переполнений
и фсе
возможно будет быстрее даже
милисек = [32bit] / 1000
/1000 = /8/125
/8 это 3 сдвига вправо и тогда 24 часа входят в [24bit]
итого, нужна процедура деления [24bit] на 125 или 3 деления подряд на 5
получить секунды, это дальше делить на 60, это 2 сдвига и процедура деления на 15 [или на 5, а потом на 3]
минуты — аналогично
в остатке — часы
кактотак? 🙂
— — — Добавлено — — —
еще как вариант, сдвинуть вначале = /8, получив [24bit]
и далее только вычитанием
-450000 до переполнения = часы
-7500 до переполнения = минуты
-125 до переполнения = секунды
остаток = миллисекунды (деленные на 8)
NEO SPECTRUMAN
12.05.2017, 23:29
4 таблицы по 1.5К (может даже меньше тк младшие 2 байта не могут указывать количество часов)
для каждого байта 32 битного числа
точнее
000000FF = 0-255мс (1 таблица 256 байт)
0000FF00 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-1мин (1 таблица или сравнение)
00FF0000 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-59мин (1 таблица) 0-4час (1 таблица или сравнение)
FF000000 = 0-999мс (2 таблицы) 0-59с (1 таблица) 0-59мин (1 таблица) 0-1188 часов (2 таблицы)
итого
16 таблиц по 256 байт
4К таблиц
или
14 таблиц по 256 байт
3.5К таблиц
если не нужны миллисекунды то можно выкинуть 1.75К
Дмитрий2012
13.05.2017, 12:28
Спасибо всем за предложенные алгоритмы, возьму на заметку.
Остановился пока на варианте, который реально могу реализовать сам с моим уровнем знания ассемблера, использующем алгоритм с процедурой деления Unsigned 24 / 16
Time – время в миллисекундах
ms=(time mod 1000)
time1=(time div 1000)
sec=(time1 mod 60)
time2=(time1 div 60)
min=(time2 mod 60)
time3=(time2 div 60)
hour=(time3 mod 24)
blackmirror
13.05.2017, 13:16
Дмитрий2012, если время потом нужно вывести, то как предложил char можно сделать табличку с константами 864000000, 86400000, 36000000, 3600000, 600000, 60000, 10000, 1000, 100, 10, 1 и подсчитывая сколько раз их можно вычесть без переполнения, сразу получать нужные цифры. Причём первые три константы имеют нулевой младший байт, что позволяет вычитать только старшие три байта, после этого останется число не более 36000000, которое не влезает в три байта, но если его и остальные константы умножить на 2, то на этом шаге тоже можно будет обойтись 24-битным вычитанием, после вычитания 2*10000 можно перейти к 16-битному вычитанию, а после вычитания 2*100 остаётся 8-битное, ну а для последней цифры цикл уже не нужен, нужно только поделить остаток на 2. Есть сильное подозрение, что данный алгоритм будет работать быстрее чем деление на 1000, 60, 60 и 24.
а вообще, все это жесткая порнуха; кто миллисекунды увеличивает? на прерываниях? ну и делается это тогда отдельными счетчиками на мсек/сек/мин/час, увеличивающимися друг за другом, зачем вообще процессор и такты излишне жечь делением?! )
Дмитрий2012
13.05.2017, 15:45
Дмитрий2012, если время потом нужно вывести, то как предложил char можно сделать табличку с константами
Пока «мотаю на ус» С табличками не знаком, никогда не использовал их. Возможно попробую и такой вариант для саморазвития, как только сделаю вариант с делением.
а вообще, все это жесткая порнуха; кто миллисекунды увеличивает? на прерываниях?
миллисекунды считает «железка» и хранит у себя. И в одном из пунктов меню утилиты, которую пишу для этой «железки» процессор занят только выводом на экран этого времени. Можно сказать это простой «показометр». Так что в данном случае не критично как перекодировать время. Главное, чтобы правильно на экран выводилось в часах, минутах, секундах … 🙂
Немного с опозданием но закину свои 66 байт
device zxspectrum48
org #8000
start
ld hl,(tick)
ld de,(tick+2)
ld c, 10
call div41
ld c, 100
call div41
ld (hdr),a
ld c, 60
call div41
ld (sec),a
ld c, 60
call div41
ld (min),a
ld (hour),hl
jr $
tick db 0,10,0,0
hdr db 0
sec db 0
min db 0
hour dw 0
div41
;dehl/c=dehl(a)
xor a
ld b, #20
.l1
add hl,hl
rl e
rl d
rla
cp c
jr c,.l2
sub c
inc l
.l2
djnz .l1
ret
savesna «time.sna»,start
Около 8к тактов, разделяет на сотые, секунды, минуты и часы. Буду рад если окажется полезным.
NEO SPECTRUMAN
13.05.2017, 19:12
С табличками не знаком, никогда не использовал их.
к примеру нарисую умножение на 3 по табличке
ld h,$c0 ;старший адрес таблички
ld l,a ;то что нужно умножить
ld a,(hl) ;получаем результат
;сама табличка
org $c000
defb 0*3
defb 1*3
defb 2*3
defb 3*3
….
;и так до
defb 255*3
если нам не хватает 8 бит для результата
ld h,$c0 ;старший адрес таблички
ld l,a ;то что нужно умножить
ld с,(hl) ;получаем младший байт результат
inc h ; меняем табличку
ld b,(hl) ;получаем старший байт результата
;сама табличка
org $c000
defb (0*3) % 256 ;% — остаток от деления. в sjasmplus можно low (0*3)
defb (1*3) % 256
defb (2*3) % 256
defb (3*3) % 256
….
;и так до
defb (255*3)% 256
org $c100
defb (0*3) / 256 ; в sjasmplus можно high (0*3)
defb (1*3) / 256
defb (2*3) / 256
defb (3*3) / 256
….
;и так до
defb (255*3) / 256
с таким же успехом можно делать таблички в другой плоскости (правда с некоторыми ограничениями)
в l заносить номер таблички
а в h подставлять данные для обработки
таким образом можно запихнуть любое количество операций любой сложности с одной переменной
(нет можно и с несколькими конечно но это уже сложней и памяти жрет неимоверно)
http://i33.fastpic.ru/big/2017/0513/eb/c40f8e8328684daaa337f75d967eb8eb.png
NEO SPECTRUMAN
13.05.2017, 19:27
Шынни, для демок или игр да
а для поставленной задачи точность скорей всего уедет
да и для 32 битных чисел…
ладно не могу вспомнить
есть єта формула у меня или нет
поставлю спасибку
Немного с опозданием но закину свои 66 байт
Около 8к тактов, разделяет на сотые, секунды, минуты и часы. Буду рад если окажется полезным.
если за скоростью не бегать (можно /10 /100, а можно /8сдвигом /125), то нормально, почему нет 🙂
еще вместо повторения ld c,60, перед div41 дописать и вызывать можно div60 ld c,60 😉
еще вместо повторения ld c,60, перед div41 дописать и вызывать можно div60 ld c,60
Ну поучавствую в соревновании кэпов, второй ld c,60 можно вообще не писать, он не меняется
если за скоростью не бегать (можно /10 /100, а можно /8сдвигом /125), то нормально, почему нет
Ну сотые напечатать нормально, че нет то, а 125-ые как то не нативно
там ему тысячные так-то нужны были, а не сотые…
сначала можно сохранить 3 мл. бита, а в конце, после трех add hl,hl, восстановить or’ом, ежели по уму делать 🙂
Powered by vBulletin® Version 4.2.5 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot
x86 — язык ассемблера — как сделать по модулю?
Если ваш модуль / делитель — известная константа, и вы заботитесь о производительности, посмотрите this и this. Мультипликативный обратный возможен даже для инвариантных к циклу значений, которые неизвестны до времени выполнения, например см. https://libdivide.com/ (Но без JIT-генератора это менее эффективно, чем жесткое кодирование, только шаги, необходимые для одной константы.)
Никогда не используйте div
для известных степеней двойки: это намного медленнее, чем и
для остатка или сдвиг вправо для деления.Посмотрите на вывод компилятора C примеры беззнакового или знакового деления на степени 2, например в проводнике компилятора Godbolt. Если вы знаете, что вход во время выполнения — степень двойки, используйте lea eax, [esi-1]
; и eax, edi
или что-то в этом роде, чтобы сделать x & (y-1)
. Modulo 256 еще более эффективен: movzx eax, cl
имеет нулевую задержку на последних процессорах Intel (удаление mov), если два регистра разделены.
В простом / общем случае: неизвестное значение во время выполнения
Команда DIV
(и ее аналог IDIV
для чисел со знаком) дает как частное, так и остаток.Для беззнакового остатка и модуля — это одно и то же. Для подписанного idiv
он дает вам остаток (не модуль), который может быть отрицательным:
, например. -5 / 2 = -2 бэр -1
. Семантика деления x86 точно соответствует оператору %
C99.
DIV r32
делит 64-битное число в EDX: EAX
на 32-битный операнд (в любом регистре или памяти) и сохраняет частное в EAX
, а остаток в EDX
. Ошибка при переполнении частного.
Пример 32-битного без знака (работает в любом режиме)
mov eax, 1234; низкая половина дивидендов
mov edx, 0; дивидендная высокая половина = 0. предпочитаю xor edx, edx
mov ebx, 10; делителем может быть любой регистр или память
div ebx; Делит 1234 на 10.
; EDX = 4 = 1234% остаток 10
; EAX = 123 = частное 1234/10
В 16-битной сборке вы можете сделать div bx
, чтобы разделить 32-битный операнд в DX: AX
на BX
.Дополнительную информацию см. В Руководстве разработчика программного обеспечения для архитектур Intel.
Обычно всегда используйте xor edx, edx
перед беззнаковым div
для расширения EAX нулями в EDX: EAX. Вот как вы делаете «нормальное» 32-битное / 32-битное => 32-битное деление.
Для разделения со знаком используйте cdq
перед idiv
– знак -расширение EAX в EDX: EAX. См. Также Почему EDX должен быть 0 перед использованием инструкции DIV ?.Для других размеров операндов используйте cbw
(AL-> AX), cwd
(AX-> DX: AX), cdq
(EAX-> EDX: EAX) или cqo
(RAX-> RDX. : RAX), чтобы установить верхнюю половину на 0
или -1
в соответствии со знаковым битом младшей половины.
div
/ idiv
доступны с размерами операндов 8, 16, 32 и (в 64-битном режиме) 64-битными. 64-битный размер операнда намного медленнее, чем 32-битный или меньше на текущих процессорах Intel, но процессоры AMD заботятся только о фактической величине чисел, независимо от размера операнда.
Обратите внимание, что 8-битный размер операнда является особенным: неявные входы / выходы находятся в AH: AL (также известном как AX), а не в DL: AL. См. Сборку 8086 на DOSBox: Ошибка с инструкцией idiv? для примера.
Пример 64-битного деления со знаком (требуется 64-битный режим)
mov rax, 0x8000000000000000; INT64_MIN = -9223372036854775808
mov ecx, 10; неявное нулевое расширение подходит для положительных чисел
cqo; знак-расширение в RDX, в данном случае = -1 = 0xFF...FF
idiv rcx
; частное = RAX = -922337203685477580 = 0xf333333333333334
; остаток = RDX = -8 = 0xfffffffffffffff8
Ограничения / типичные ошибки
div dword 10
не кодируется в машинный код (поэтому ваш ассемблер сообщит об ошибке о недопустимых операндах).
В отличие от mul
/ imul
(где обычно следует использовать более быстрый 2-операнд imul r32, r / m32
или 3-операнд imul r32, r / m32, imm8 / 32
вместо этого, время записи результата с высокой половиной), нет более нового кода операции для деления на немедленное или 32-битное / 32-битное => 32-битное деление или остаток без ввода делимого с высокой половиной.
Division настолько медленная и (надеюсь) редкая, что они не удосужились добавить способ, позволяющий избежать EAX и EDX, или использовать немедленное использование напрямую.
div и idiv выдадут ошибку, если частное не помещается в один регистр (AL / AX / EAX / RAX, такая же ширина, как и делимое). Это включает деление на ноль, но также может произойти с ненулевым EDX и меньшим делителем. Вот почему компиляторы C просто расширяют нулем или расширяют знак вместо разделения 32-битного значения на DX: AX.
А также, почему INT_MIN / -1
— это неопределенное поведение C: оно превышает знаковое частное в системах с дополнением до 2, таких как x86. См. Почему целочисленное деление на -1 (отрицательное) приводит к FPE? для примера x86 vs. ARM. x86 idiv
действительно в этом случае неисправен.
Исключение x86: #DE
— исключение разделения. В системах Unix / Linux ядро доставляет арифметический сигнал исключения SIGFPE процессам, вызывающим исключение #DE. (На каких платформах целочисленное деление на ноль вызывает исключение с плавающей запятой?)
Для div
безопасно использовать делимое с high_half
0x11: 23 / 0x12
меньше, чем 0xff
, поэтому он умещается в 8-битном частном.
Деление большого числа на малое с повышенной точностью может быть реализовано путем использования остатка от одного фрагмента в качестве делимого с высокой половиной (EDX) для следующего фрагмента. Вероятно, поэтому они выбрали остаток = EDX quotient = EAX, а не наоборот.
Руководство по сборке x86
Это версия, адаптированная Квентином Карбонно из книги Дэвида Эванса.
оригинальный документ.Синтаксис был изменен с Intel на AT&T,
стандартный синтаксис в системах UNIX, и код HTML был очищен.
В этом руководстве описаны основы 32-разрядного языка ассемблера x86.
программирование, охватывающее небольшое, но полезное подмножество доступных
инструкции и директивы ассемблера. Есть несколько разных
языки ассемблера для генерации машинного кода x86. Тот, который мы будем использовать
в CS421 - ассемблер GNU Assembler (gas). Мы будем использовать
стандартный синтаксис AT&T для написания ассемблерного кода x86.
Полный набор инструкций x86 большой и сложный (Intel x86
инструкции по эксплуатации содержат более 2900 страниц), и мы не покрываем
все это в этом руководстве. Например, есть 16-битное подмножество x86
набор инструкций. Использование 16-битной модели программирования может быть довольно
сложный. Имеет сегментированную модель памяти, больше ограничений на регистр
использование и так далее. В этом руководстве мы ограничим наше внимание другими
современные аспекты программирования x86 и углубиться в набор инструкций
только достаточно подробно, чтобы получить базовое представление о программировании x86.
Регистры
Современные (например, 386 и более поздние) процессоры x86 имеют восемь 32-разрядных общих
регистры назначения, как показано на рисунке 1. Имена регистров
в основном исторический. Например, EAX раньше назывался
аккумулятор, поскольку он использовался для ряда арифметических операций, и
ECX был известен как счетчик, поскольку он использовался для удержания цикла.
показатель. Принимая во внимание, что большинство регистров утратили свое специальное назначение в
в современном наборе команд по соглашению две зарезервированы для специальных
цели - указатель стека (ESP) и базовый указатель
(EBP).
Для EAX, EBX, ECX и
Можно использовать регистры EDX, подразделы. Например, наименее
2 значимых байта EAX можно рассматривать как 16-битный регистр
называется AX. Младший байт AX может быть
используется как один 8-битный регистр, называемый AL, в то время как большинство
значащий байт AX может использоваться как один 8-битный регистр
называется AH. Эти имена относятся к одному и тому же физическому
регистр. Когда двухбайтовое количество помещается в DX,
обновление влияет на значение DH, DL и
EDX. Эти подрегистры в основном являются пережитками старых,
16-битные версии набора команд.Однако иногда они
удобно при работе с данными размером менее 32 бит
(например, 1-байтовые символы ASCII).
Рисунок 1. Регистры x86
Память и режимы адресации
Объявление областей статических данных
Вы можете объявить статические области данных (аналогичные глобальным переменным) в
x86, используя для этого специальные директивы ассемблера. Данные
объявлениям должен предшествовать .data
директива. Следуя этой директиве, директивы.byte, .short и .long можно использовать для объявления одного, двух и четырех байтов.
расположения данных соответственно. Чтобы сослаться на адрес созданных данных,
мы можем обозначить их. Этикетки очень удобны и универсальны в сборке, они
давать имена ячейкам памяти, которые позже выяснит ассемблер
или компоновщик. Это похоже на объявление переменных по имени, но соблюдается
некоторые правила нижнего уровня. Например, местоположения, объявленные последовательно, будут
расположены в памяти рядом друг с другом.
Примеры объявлений:
.данные var: .byte 64 . Байт 10 x: . Короткий 42 г: . Длинный 30000
В отличие от языков высокого уровня, где массивы могут иметь много измерений и
доступны с помощью индексов, массивы на языке ассемблера x86 - это просто
количество ячеек, расположенных в памяти подряд.Можно объявить массив
просто перечислив значения, как в первом примере ниже.
Для особого случая массива байтов можно использовать строковые литералы.
Если большая область памяти заполнена нулями,
Можно использовать директиву .zero.
Некоторые примеры:
с: . Длинные 1, 2, 3 барр: . Ноль 10 ул: .строка "привет"
Адресная память
Современные x86-совместимые процессоры способны адресовать до
2 32 байт памяти: адреса памяти имеют ширину 32 бита. В
приведенные выше примеры, где мы использовали метки для обозначения областей памяти,
эти метки фактически заменены ассемблером на 32-битный
количества, указывающие адреса в памяти. Помимо поддержки
ссылаясь на области памяти метками (то есть постоянными значениями), x86
обеспечивает гибкую схему вычислений и обращения к памяти
адреса: до двух 32-битных регистров и 32-битный подписанный
константу можно сложить вместе, чтобы вычислить адрес памяти.Один из
регистры можно дополнительно предварительно умножить на 2, 4 или 8.
Режимы адресации можно использовать со многими инструкциями x86.
(мы опишем их в следующем разделе). Здесь мы проиллюстрируем несколько примеров
используя инструкцию mov, которая перемещает данные
между регистрами и памятью. Эта инструкция имеет два операнда:
первый - это источник, а второй - пункт назначения.
Некоторые примеры инструкций mov
с использованием адресных вычислений:
mov (% ebx),% eax mov% ebx, var (, 1) mov -4 (% esi),% eax mov% cl, (% esi,% eax, 1) mov (% esi,% ebx, 4),% edx
Вот некоторые примеры неверных вычислений адреса:
mov (% ebx,% ecx, -1),% eax mov% ebx, (% eax,% esi,% edi, 1)
Суффиксы операций
В общем, предполагаемый размер элемента данных в данной памяти
адрес можно вывести из инструкции кода сборки, в которой он
упоминается.Например, во всех приведенных выше инструкциях размер
областей памяти можно определить по размеру регистра
операнд. Когда мы загружали 32-битный регистр, ассемблер мог
сделайте вывод, что область памяти, о которой мы говорили, была 4 байта
широкий. Когда мы сохраняли значение однобайтового регистра в памяти,
ассемблер мог сделать вывод, что мы хотим, чтобы адрес ссылался на
один байт в памяти.
Однако в некоторых случаях размер упомянутой области памяти составляет
двусмысленный.Рассмотрим инструкцию mov $ 2, (% ebx).
Если эта инструкция переместит значение 2 в
однобайтный по адресу EBX? Возможно
он должен переместить 32-битное целочисленное представление 2 в 4-байтовое
начиная с адреса EBX. Поскольку либо
является допустимой возможной интерпретацией, ассемблер должен быть явно
направлено относительно того, какой из них правильный. Префиксы размера b, w,
и я служу этой цели,
с указанием размеров 1, 2 и 4 байта соответственно.
Например:
movb $ 2, (% ebx) movw $ 2, (% ebx) movl $ 2, (% ebx)
Инструкции
Машинные инструкции обычно делятся на три категории: данные
движение, арифметика / логика и поток управления.В этом разделе мы будем
посмотрите важные примеры инструкций x86 из каждой категории. Этот
раздел не следует рассматривать как исчерпывающий список инструкций x86,
а скорее полезное подмножество. Для получения полного списка см. Intel
ссылка на набор команд.
Мы используем следующие обозначения:
Любые
32-битный регистр (% eax,
% ebx,
% ecx,
% edx,
% esi,
% edi,
% esp или
% ebp)Любые
16-битный регистр (% ax,
% bx,
% cx, или
% dx)Любые
8-битный регистр (% ah,
% bh,
% ch,
% dh,
% al,
% bl,
% cl, или
% dl)Любой регистр Адрес памяти (например,г., (% eax), 4 + var (, 1),
или (% eax,% ebx, 1))Любая 32-битная немедленная Любой 16-битный немедленный Любой 8-битный немедленный Любой 8-, 16- или 32-битный немедленный
В ассемблере все метки и числовые константы, используемые как непосредственные операнды.
(т.е. не при вычислении адреса, например 3 (% eax,% ebx, 8))
всегда начинаются со знака доллара.При необходимости можно использовать шестнадцатеричное представление.
использовать с префиксом 0x
(например, $ 0xABC). Без префикса числа
интерпретируется в десятичной системе счисления.
Инструкции по перемещению данных
mov - Перемещение
Инструкция mov копирует элемент данных, на который указывает
его первый операнд (т.е. содержимое регистра, содержимое памяти или константа
значение) в место, на которое указывает его второй операнд (т.е. регистр или
объем памяти). Хотя возможны перемещения из регистра в регистр, прямой переход из памяти в память
ходов нет.В случаях, когда требуется передача памяти, исходная память
содержимое должно быть сначала загружено в регистр, а затем может быть сохранено в
адрес памяти назначения.Синтаксис
mov,
mov,
mov,
mov,
mov, Примеры
mov% ebx,% eax - скопируйте значение из EBX в EAX
movb $ 5, var (, 1) - сохраните значение 5 в
байт в местоположении var
push - Нажать на стек
Инструкция push помещает свой операнд в
верхняя часть стека, поддерживаемого оборудованием, в памяти.В частности, push сначала уменьшает ESP на 4, затем помещает его
операнд в содержимое 32-битной ячейки по адресу (% esp). ESP
(указатель стека) уменьшается нажатием, так как стек x86 растет
вниз - то есть стек растет от старших адресов к младшим.Синтаксис
push
push
pushПримеры
push% eax - поместить eax в стек
push var (, 1) - поместить 4 байта в
адрес var в стек
pop - Поп из стека
Команда pop удаляет 4-байтовые данные
элемент из вершины стека с аппаратной поддержкой в указанный
операнд (т.е. регистр или место в памяти). Сначала перемещает 4 байта
расположен в ячейке памяти (% esp) в
указанный регистр или ячейку памяти, а затем увеличивает ESP на 4.Синтаксис
pop
popПримеры
pop% edi - вставить верхний элемент стека в EDI.
pop (% ebx) - выталкивает верхний элемент
стек в память в четырех байтах, начиная с позиции EBX.
lea - Загрузить эффективный адрес
Инструкция lea помещает адрес , указанный в его первом операнде.
в регистр, указанный его вторым операндом.Обратите внимание, что содержимое ячейки памяти не
загружается, вычисляется и помещается в регистр только эффективный адрес.
Это полезно для получения указателя на область памяти или для выполнения простых
арифметические операции.Синтаксис
lea, Примеры
lea (% ebx,% esi, 8),% edi - количество EBX + 8 * ESI помещается в EDI.
lea val (, 1),% eax - значение val помещается в EAX.
Арифметические и логические инструкции
add - Целочисленное сложение
Инструкция добавления добавляет
вместе два операнда, сохраняя результат во втором
операнд.Обратите внимание: в то время как оба операнда могут быть регистрами, не более одного
операнд может быть ячейкой памяти.Синтаксис
добавить,
добавить,
добавить,
добавить,
добавить, Примеры
добавить 10 долларов,% eax - EAX установлен на EAX + 10
addb 10 долларов, (% eax) - добавить 10 к
один байт хранится по адресу памяти, хранящемуся в EAX
sub - Целочисленное вычитание
Дополнительная инструкция хранит значение
его второй операнд - результат вычитания значения его первого
операнд из значения его второго операнда.Как и в случае с add, в то время как оба операнда могут быть регистрами, не более
один операнд может быть ячейкой памяти.Синтаксис
sub,
sub,
sub,
sub,
sub, Примеры
sub% ah,% al - AL установлен на AL - AH
sub $ 216,% eax - вычесть 216 из
значение хранится в EAX
inc, dec - Increment, Decrement
Инкремент инструкции inc
содержимое его операнда на единицу.Декабрь
инструкция уменьшает содержимое своего операнда на единицу.Синтаксис
inc
inc
dec
decПримеры
dec% eax - вычтите единицу из содержимого EAX
, включая var (, 1) - добавьте единицу к
32-битное целое число, хранящееся в ячейке var
imul - Целочисленное умножение
Инструкция imul имеет два основных формата:
два операнда (первые два списка синтаксиса выше) и три операнда (последний
два списка синтаксиса выше).Форма с двумя операндами умножает свои два операнда вместе и сохраняет результат
во втором операнде. Результат (то есть второй) операнд должен быть
регистр.Форма с тремя операндами умножает свои второй и третий операнды вместе
и сохраняет результат в своем последнем операнде. Опять же, операнд результата
должен быть реестр. Кроме того, первый операнд ограничен
постоянное значение.Синтаксис
imul,
imul,
imul, ,
imul, , Примеры
imul (% ebx),% eax - умножить содержимое
EAX 32-битным содержимым памяти в ячейке EBX.Магазин
результат в EAX.imul $ 25,% edi,% esi - для ESI установлено значение EDI * 25
idiv - Целочисленное деление
Инструкция idiv делит
содержимое 64-битного целого числа EDX: EAX (созданное путем просмотра EDX как
старшие четыре байта и EAX как младшие четыре
байтов) на указанное значение операнда. Результат частного
деление сохраняется в EAX, а остаток помещается в EDX.Синтаксис
idiv
idivПримеры
idiv% ebx - разделить содержимое
EDX: EAX по содержимому EBX.Поместите частное в EAX и
остаток в EDX.idivw (% ebx) - разделить
содержимое EDX: EAS 32-битным значением, хранящимся в ячейке памяти в
EBX. Поместите частное в EAX, а остаток в EDX.
and, or, xor - Побитовая логика
и, или, и исключающее, или
Эти инструкции выполняют указанную логическую операцию (логический
побитовое и, или, и исключающее или, соответственно) на своих операндах, помещая
приведет к расположению первого операнда.Синтаксис
и,
и,
и,
и,
и, или
,
или,
или,
или,
или, xor
,
xor,
xor,
xor,
xor, Примеры
и $ 0x0f,% eax - удалить все, кроме последних 4
биты EAX.
xor% edx,% edx - установить содержимое EDX
до нуля.
not - Побитовое логическое не
Логически инвертирует содержимое операнда (то есть переворачивает все битовые значения в
операнд).Синтаксис
не
неПример
not% eax - перевернуть все биты EAX
neg - Отрицать
Выполняет отрицание дополнения до двух содержимого операнда.
Синтаксис
neg
negПример
neg% eax - EAX установлен на (- EAX)
shl, shr - Сдвиг влево и вправо
Эти инструкции сдвигают биты в содержимом своего первого операнда.
слева и справа, заполняя получившийся пустой бит
позиции с нулями. Сдвинутый операнд может быть сдвинут до 31 разряда. В
количество битов для сдвига определяется вторым операндом, который может быть
либо 8-битная константа, либо регистр CL.В любом случае сдвигает количество
больше 31 выполняются по модулю 32.Синтаксис
shl,
shl,
shl% cl,
shl% cl,shr
,
shr,
shr% cl,
shr% cl,Примеры
shl $ 1, eax - Умножить значение EAX
на 2 (если старший бит 0)shr% cl,% ebx - Магазин в EBX на этаже
результат деления значения EBX на 2 n , где n - это
значение в CL.Внимание: для отрицательных целых чисел это отличается от от C
семантика деления!
Инструкции по потоку управления
Процессор x86 поддерживает регистр указателя инструкций (EIP), который
32-битное значение, указывающее место в памяти, где текущий
инструкция начинается. Обычно он увеличивается, чтобы указать на следующий
инструкция в памяти начинается после выполнения инструкции. EIP
регистр нельзя манипулировать напрямую, но он неявно обновляется
предоставил инструкции по потоку управления.
Мы используем обозначение
mov 8 (% ebp),% esi начинать: xor% ecx,% ecx mov (% esi),% eax
Вторая инструкция в этом фрагменте кода помечена как начало. В другом месте кода мы можем ссылаться на
место в памяти, в котором эта инструкция находится в памяти, используя
более удобное символьное имя begin.Этот
метка - это просто удобный способ обозначить местоположение, а не его
32-битное значение.
jmp - прыжок
Передает поток управления программой инструкции в памяти
местоположение, указанное операндом.Синтаксис
jmp <метка>Пример
jmp begin - Перейти к инструкции
помечены как начало.
j condition - Условный переход
Эти инструкции представляют собой условные переходы, основанные на состоянии
набор кодов условий, которые хранятся в специальном регистре, называемом
слово состояния машины .Содержание статуса машины
слово включает информацию о последней арифметической операции
выполненный. Например, один бит этого слова указывает, что последний
результат был нулевым. Другой указывает, был ли последний результат
отрицательный. На основе этих кодов условий выполняется ряд условных переходов.
может быть выполнено. Например, jz
инструкция выполняет переход к указанной метке операнда, если результат
последней арифметической операции был равен нулю. В противном случае контроль продолжается
к следующей инструкции по порядку.Некоторым условным ветвям даны имена, которые
интуитивно на основе последней выполненной операции являясь специальным
инструкция сравнения, cmp (см. ниже). Например, условные переходы
такие как jle и jne, основаны на первом выполнении операции cmp
на желаемых операндах.Синтаксис
jeПример
cmp% ebx,% eax jle сделаноЕсли содержимое EAX меньше или равно содержимому EBX,
переход к метке выполнено .В противном случае переходите к следующему
инструкция.
cmp - Сравнить
Сравните значения двух указанных операндов, задав условие
соответствующие коды в слове состояния машины. Эта инструкция
эквивалент субинструкции, за исключением
результат вычитания отбрасывается вместо замены первого
операнд.Синтаксис
cmp,
cmp,
cmp,
cmp, Пример
cmpb $ 10, (% ebx)
jeq loopЕсли байт, хранящийся в ячейке памяти в EBX, равен
целочисленная константа 10, переход к месту с меткой , цикл .
вызов , ret - вызов подпрограммы и возврат
Эти инструкции реализуют вызов и возврат подпрограммы.
Инструкция вызова сначала подталкивает текущий
расположение кода в стеке, поддерживаемом оборудованием, в памяти (подробности см. в инструкции push), а затем выполняет
безусловный переход к месту кода, обозначенному меткой
операнд. В отличие от простых инструкций перехода, инструкция вызова сохраняет место, куда нужно вернуться.
когда подпрограмма завершится.Инструкция ret реализует подпрограмму
возвратный механизм. Эта инструкция сначала извлекает ячейку кода из
аппаратно поддерживаемый стек в памяти (подробности см. в инструкции pop). Затем он выполняет
безусловный переход к полученному месту кода.Синтаксис
call <метка>
ret
Соглашение о вызове
Чтобы отдельные программисты могли совместно использовать код и разрабатывать библиотеки для
использование многими программами, а также для упрощения использования подпрограмм в целом,
программисты обычно принимают общее соглашение о вызовах .В
соглашение о вызовах - это протокол о том, как звонить и возвращаться из
рутины. Например, учитывая набор правил соглашения о вызовах,
программисту не нужно проверять определение подпрограммы, чтобы определить
как параметры должны быть переданы этой подпрограмме. Кроме того, учитывая
набор правил соглашения о вызовах, компиляторы языков высокого уровня могут быть
сделано в соответствии с правилами, что позволяет вручную кодировать язык ассемблера
подпрограммы и подпрограммы языка высокого уровня для вызова друг друга.
На практике возможно множество соглашений о вызовах.Мы опишем
широко используемое соглашение о вызовах языка C. Следуя этой конвенции
позволит вам писать подпрограммы на языке ассемблера, которые безопасно
вызывается из кода C (и C ++), а также позволяет вызывать C
библиотечные функции из кода вашего ассемблера.
Соглашение о вызовах C в значительной степени основано на использовании
стек с аппаратной поддержкой. Он основан на push, pop, call и ret.
инструкции. Параметры подпрограммы передаются в стек. Регистры
сохраняются в стеке, а локальные переменные, используемые подпрограммами,
помещается в память в стеке.Подавляющее большинство высокоуровневых
процедурные языки, реализованные на большинстве процессоров, использовали аналогичные
соглашения о вызовах.
Соглашение о вызовах разбито на два набора правил. Первый набор
правил используется вызывающей подпрограммой, а второй набор
правил соблюдается автором подпрограммы (вызываемым). Это
Следует подчеркнуть, что ошибки при соблюдении этих правил
быстро привести к фатальным программным ошибкам, так как стек останется в
противоречивое состояние; поэтому следует проявлять тщательную осторожность при
реализация соглашения о вызовах в ваших собственных подпрограммах.
Стек во время вызова подпрограммы
[Спасибо Джеймсу Петерсону за обнаружение и исправление ошибки в
оригинальная версия этого рисунка!]
Хороший способ визуализировать работу соглашения о вызовах - это
рисовать содержимое соседней области стека во время подпрограммы
исполнение. На изображении выше показано содержимое стека во время
выполнение подпрограммы с тремя параметрами и тремя локальными
переменные. Ячейки, изображенные в стопке
являются 32-битными ячейками памяти, поэтому адреса ячеек памяти
разделены на 4 байта.Первое
Параметр находится со смещением 8 байтов от базового указателя. Выше
параметры в стеке (и ниже базового указателя), инструкция вызова помещает адрес возврата, таким образом
приводит к дополнительным 4 байтам смещения от базового указателя до первого
параметр. Когда используется инструкция ret
чтобы вернуться из подпрограммы, он перейдет к сохраненному адресу возврата
в стеке.
Правила для вызывающего абонента
Чтобы выполнить вызов подпрограммы, вызывающий должен:
- Перед вызовом подпрограммы вызывающий должен
сохранять содержимое определенных регистров, которые обозначены
сохранено абонентом .Регистры, сохраненные вызывающим абонентом, - это EAX, ECX, EDX.
Поскольку вызываемой подпрограмме разрешено изменять эти регистры, если
вызывающий полагается на их значения после возврата из подпрограммы, вызывающий
должны помещать значения из этих регистров в стек (чтобы они могли быть
восстановить после возврата из подпрограммы. - Чтобы передать параметры подпрограмме, поместите их в стек
перед звонком. Параметры следует вводить в обратном порядке.
(т.е. сначала последний параметр). Поскольку стек растет вниз, первый
параметр будет сохранен по наименьшему адресу (эта инверсия
параметры исторически использовались, чтобы разрешить передачу функций
переменное количество параметров). - Для вызова подпрограммы используйте вызов
инструкция. Эта инструкция помещает обратный адрес поверх
параметры в стеке и переходят к коду подпрограммы. Этот
вызывает подпрограмму, которая должна следовать приведенным ниже правилам вызываемого объекта.
После возврата из подпрограммы (сразу после инструкции вызова) вызывающий может ожидать, что найдет
возвращаемое значение подпрограммы в регистре EAX. Чтобы восстановить
состояние машины, вызывающий должен:
- Удалить параметры из стека.Это восстанавливает стек в его
состояние до выполнения вызова. - Восстановить содержимое регистров, сохраненных вызывающим абонентом (EAX, ECX, EDX),
вытаскивая их из стопки. Вызывающий может предположить, что никто другой
регистры были изменены подпрограммой.
Пример
В приведенном ниже коде показан вызов функции, который следует правилам вызывающего объекта. В
вызывающий вызывает функцию myFunc , которая принимает три целых числа
параметры. Первый параметр находится в EAX, второй параметр - это
постоянная 216; третий параметр находится в ячейке памяти, хранящейся в EBX.
push (% ebx) / * Передать последний параметр первым * / push $ 216 / * Нажмите второй параметр * / push% eax / * Вставить первый параметр последним * / call myFunc / * Вызов функции (предположим, что это имя C) * / добавить $ 12,% esp
Обратите внимание, что после возврата вызова вызывающий очищает стек, используя
инструкция по добавлению. У нас есть 12 байт (3
параметры * 4 байта каждый) в стеке, и стек увеличивается вниз. Таким образом,
чтобы избавиться от параметров, мы можем просто добавить 12 к указателю стека.
Результат myFunc теперь доступен для использования в
зарегистрируйте EAX. Значения регистров, сохраненных вызывающим абонентом (ECX и EDX),
могло быть изменено. Если вызывающий абонент использует их после звонка, он
нужно было сохранить их в стеке перед вызовом и восстановить их
после этого.
Правила вызываемого абонента
Определение подпрограммы должно соответствовать следующим правилам на
начало подпрограммы:
- Поместите значение EBP в стек, а затем скопируйте значение ESP
в EBP, используя следующие инструкции:нажать% ebp mov% esp,% ebp
Это начальное действие поддерживает базовый указатель , EBP.База
указатель используется по соглашению как точка отсчета для поиска
параметры и локальные переменные в стеке. Когда подпрограмма
при выполнении базовый указатель содержит копию значения указателя стека из
когда подпрограмма начала выполняться. Параметры и локальные переменные
всегда будет располагаться на известных постоянных смещениях от основания
значение указателя. Мы помещаем старое значение базового указателя в начало
подпрограмму, чтобы позже мы могли восстановить соответствующий базовый указатель
значение для вызывающего при возврате подпрограммы.Помните, звонящий
не ожидает, что подпрограмма изменит значение базы
указатель. Затем мы перемещаем указатель стека в EBP, чтобы получить нашу точку
справочник для доступа к параметрам и локальным переменным. - Затем выделите локальные переменные, освободив место на
куча. Напомним, стек растет вниз, чтобы освободить место наверху
стек, указатель стека должен быть уменьшен. Сумма, на которую стек
указатель уменьшается в зависимости от количества и размера локальных переменных
нужный.Например, если требовалось 3 локальных целых числа (по 4 байта каждое),
указатель стека необходимо уменьшить на 12, чтобы освободить место для
эти локальные переменные (т. е. $ 12,% esp).
Как и в случае с параметрами, локальные переменные будут располагаться на известных смещениях.
от базового указателя. - Затем сохраните значения сохраненных вызываемым пользователем регистров , которые
будет использоваться функцией. Чтобы сохранить регистры, вставьте их в
куча. Регистры, сохраненные вызываемым пользователем: EBX, EDI и ESI (ESP и EBP.
также будет сохранен соглашением о вызовах, но не нужно нажимать
в стеке на этом этапе).
После выполнения этих трех действий тело
подпрограмма может продолжаться. Когда подпрограмма возвращается, она должна следовать
эти шаги:
- Оставьте возвращаемое значение в EAX.
- Восстановить старые значения всех регистров, сохраненных вызываемым пользователем (EDI и ESI)
которые были изменены. Содержимое регистров восстанавливается путем их выскакивания
из стека. Регистры должны быть вставлены в обратном порядке.
приказ, чтобы их толкнули. - Освободить локальные переменные.Очевидный способ сделать это -
добавить соответствующее значение в указатель стека (поскольку пробел был
выделяется путем вычитания нужной суммы из указателя стека). В
На практике менее подверженный ошибкам способ освободить переменные - это
переместите значение из базового указателя в указатель стека: mov% ebp,% esp. Это работает, потому что
базовый указатель всегда содержит значение, которое указатель стека содержал сразу
до распределения локальных переменных. - Непосредственно перед возвратом восстановить базовый указатель вызывающего абонента
значение, извлекая EBP из стека.Напомним, что первое, что мы сделали на
вход в подпрограмму должен был нажать базовый указатель, чтобы сохранить его старый
ценить. - Наконец, вернитесь к вызывающему, выполнив команду ret. Эта инструкция найдет и
удалить из стека соответствующий адрес возврата.
Обратите внимание на то, что правила вызываемого четко разделяются на две половины, которые
в основном зеркальное отображение друг друга. Первая половина правил
применяются к началу функции и обычно говорят
для определения пролога функции.Вторая половина
правила применяются к концу функции, и поэтому обычно говорят, что
определить эпилог функции.
Пример
Вот пример определения функции, которая следует правилам вызываемого объекта:
/ * Запуск раздела кода * / .текст / * Определим myFunc как глобальную (экспортируемую) функцию. * / .globl myFunc .type myFunc, @ функция myFunc: / * Пролог подпрограммы * / push% ebp / * Сохранить старое значение базового указателя.* / mov% esp,% ebp / * Устанавливает новое значение базового указателя. * / sub $ 4,% esp / * Освободите место для одной 4-байтовой локальной переменной. * / push% edi / * Сохранить значения регистров, которые функция * / push% esi / * изменит. Эта функция использует EDI и ESI. * / / * (нет необходимости сохранять EBX, EBP или ESP) * / / * Тело подпрограммы * / mov 8 (% ebp),% eax / * Перенести значение параметра 1 в EAX. * / mov 12 (% ebp),% esi / * Перенести значение параметра 2 в ESI. * / mov 16 (% ebp),% edi / * Перенести значение параметра 3 в EDI.* / mov% edi, -4 (% ebp) / * Переместить EDI в локальную переменную. * / add% esi, -4 (% ebp) / * Добавить ESI в локальную переменную. * / add -4 (% ebp),% eax / * Добавить содержимое локальной переменной * / / * в EAX (конечный результат). * / / * Эпилог подпрограммы * / pop% esi / * Восстановить значения регистров. * / поп% edi mov% ebp,% esp / * Освободите локальную переменную. * / pop% ebp / * Восстанавливает значение базового указателя вызывающего. * / Ret
Пролог подпрограммы выполняет стандартные действия по сохранению
снимок указателя стека в EBP (базовый указатель), выделяющий
локальные переменные, уменьшая указатель стека и сохраняя регистр
значения в стеке.
В теле подпрограммы мы видим использование базы
указатель. И параметры, и локальные переменные находятся на постоянных
смещения от базового указателя на время выполнения подпрограмм
исполнение. В частности, мы замечаем, что, поскольку параметры были помещены
в стек перед вызовом подпрограммы, они всегда располагаются
ниже базового указателя (то есть по более высоким адресам) в стеке. В
первый параметр подпрограммы всегда можно найти в ячейке памяти
(EBP + 8), второй - (EBP + 12), третий - (EBP + 16).Сходным образом,
поскольку локальные переменные выделяются после установки базового указателя, они
всегда находиться над базовым указателем (то есть по нижним адресам) на
куча. В частности, первая локальная переменная всегда находится в
(EBP-4), второй в (EBP-8) и так далее. Это обычное использование
базовый указатель позволяет нам быстро определять использование локальных переменных
и параметры в теле функции.
Эпилог функции - это, по сути, зеркальное отображение функции
пролог. Значения регистров вызывающего абонента восстанавливаются из стека,
локальные переменные освобождаются путем сброса указателя стека,
значение базового указателя вызывающего абонента восстанавливается, и инструкция ret
используется для возврата к соответствующему месту кода в вызывающей стороне.
Кредиты: Это руководство было первоначально создано Адамом Феррари.
лет назад,
и с тех пор обновлено Аланом Бэтсоном, Майком
Недостаток и Анита Джонс.
Пересмотрена для
216 Весна 2006 года Дэвид Эванс.
В конечном итоге он был изменен
Квентин Карбонно использует AT&T
синтаксис Йельского CS421.
Лаборатория языка ассемблера
Лаборатория языка ассемблера
CS42:
Принципы компьютерной организации
Весенний семестр 2000 г.
Рэй Онтко
Кафедра компьютерных наук
Эрлхэм Колледж
Цель этой лабораторной работы - дать вам возможность изучить
и изменять программы на ассемблере.
Представьте, что вы работаете над программой с критичным ко времени
часть, которую вы хотели бы улучшить. Ваша программа
(написано на C) использует
подход "пробного деления" к факторингу простых чисел, и в какой-то момент
вы вычисляете как частное (/), так и остаток (%). Ты
вспомните (из курса компьютерной организации в колледже), что
80386 имеет инструкцию, которая вычисляет оба одновременно
во время разделения и хотел узнать, использует ли компилятор
это оптимальный подход, а если нет, исправьте.
Итак, вы написали небольшую тестовую программу,
divrem.c,
чтобы увидеть, как компилятор
обрабатывает ситуацию:
/ * divrem.c Программа тестирования для исследования улучшений производительности в программах, содержащих / (div) с% (rem). Рэй Онтко, 16.04.2000 * / #include#include int main () { int i; int a; int b; int q; int r; а = 23; b = 5; для (i = 0; i
Используя эту программу, сделайте следующее:
- Подключитесь к системе, в которой есть компилятор Gnu C (gcc) и
ассемблер Gnu (as) и работает на процессоре Intel 386.Скопируйте указанную выше программу в файл с именем divrem.c. - Используйте следующую команду для компиляции программы:
cc divrem.c -o divrem
- Запустите программу, используя "time" или "/ usr / bin / time"
для отображения статистики по времени:время ./divrem / usr / bin / время ./divrem
Обратите внимание на различную приведенную статистику выполнения.
- Теперь используйте параметр -S компилятора Gnu, чтобы остановить компиляцию
и сохраните листинг сборки. Введите команду:cc -S divrem.c
Это создает файл "divrem.s", который содержит сборку
языковой эквивалент вашей исходной программы. - Изучите список языков ассемблера. Вы можете объяснить
смысл каждой строчки с точки зрения исходной программы? - Убедитесь, что вы можете скомпилировать и запустить ассемблер
листинг:rm divrem cc divrem.s -o divrem время ./divrem / usr / bin / время ./divrem
Здесь мы удаляем изначально скомпилированную версию программы C,
собрать и связать "диврем."s "в файл" divrem ", и, наконец,
повторно запустить программу. Опять же, обратите внимание на статистику времени. Как
они сравниваются с первоначальным запуском? - Используя ваш любимый редактор unix (, например, , vi) измените сборку
языковой файл, чтобы исключить любой избыточный код, который, по вашему мнению, может
влияют на производительность программы. - Соберите и протестируйте вашу новую программу. Это правильно работает?
Как сравнивать статистику выполнения?rm divrem cc divrem.s -o divrem время ./ divrem / usr / bin / время ./divrem
Покажите свою программу и объясните свои результаты человеку рядом с вами.
По завершении лабораторной работы сдайте статистику по времени.
и краткое описание того, какие изменения вы внесли в сборку
листинг на Intel 386.
Авторские права © 1997, 2000, г.
Рэй Онтко
( [email protected] ).
Все права защищены.
Перерыв в Законодательном собрании продлен до 4 мая; что это означает для оставшейся части сессии, процесса государственного бюджета - CSBA Blog
16 марта, сразу после передачи пакета финансирования на борьбу с пандемией COVID-19 в размере 1 миллиарда долларов (, включая 100 миллионов долларов для школ , что составляет примерно 17 долларов США.37 на среднесуточную посещаемость, которые будут отправлены местным образовательным агентствам в начале апреля), Законодательный орган отложил законодательный 2020 год до 13 апреля. Беспрецедентное прекращение работы теперь продлено.
ОБНОВЛЕНИЕ: В пятницу, 3 апреля, президент Сената проф. Тем Тони Г. Аткинс (Демократическая Республика Сан-Диего) и спикер Ассамблеи Энтони Рендон (Демократическая Республика Лейквуд) объявили в сообщении для СМИ, что они обратятся в Сенат и Ассамблею. Капитолий 4 мая. Официальное объявление 4 мая датой возвращения последовало за заявлением сенатора.Аткинс на Голос Сан-Диего ранее в тот же день объявил, что перерыв будет продлен.
Вот что это будет значить для бюджета, для новых законопроектов и на оставшуюся часть законодательного года:
2020 - 21 процесс государственного бюджета:
По закону губернатор должен опубликовать майский бюджетный пересмотр не позднее 15 мая. Как правило, бюджетные подкомитеты в Сенате и Собрании встречаются в марте и апреле для оценки бюджетных приоритетов каждой палаты по мере того, как майский пересмотр обретает форму.С 4 мая в качестве целевой даты возвращения эти комитеты столкнутся с очень коротким промежутком времени, чтобы официально встретиться перед выпуском майской редакции.
После майского пересмотра ежегодный комитет бюджетной конференции - объединенный комитет членов Сената и Ассамблеи - собирается в конце мая - начале июня, чтобы отобрать рекомендации по отдельным статьям бюджета от обеих палат и оценить новые предложения губернатора, если любой. Затем Конференционный комитет отправит согласованный бюджет обратно в обе палаты для голосования.У обеих палат есть крайний срок до 15 июня, чтобы принять бюджет и отправить его губернатору, который затем должен подписать его до 1 июля. Эти сроки установлены Конституцией Калифорнии и не подлежат отмене.
Дата возвращения 4 мая сохранит процесс работы Комитета Конференции и даст обеим палатам возможность проголосовать по бюджету. Если обстоятельства пандемии COVID-19 приведут к тому, что перерыв снова будет продлен после 4 мая, изучаются юридически жизнеспособные альтернативы, но в настоящее время неясно, есть ли у Законодательного собрания допустимый вариант для проведения голосования в комитете или зала голосования онлайн или любыми способами. кроме личного присутствия в Капитолии.
Что означает «бюджет рабочей нагрузки» на 2020–2021 годы:
24 марта Департамент финансов Калифорнии выпустил письмо относительно государственного бюджета на 2020–21 годы, предшествовавшее майской редакции , в котором говорилось, что Министерство финансов теперь переоценивает все изменения бюджета в контексте бюджета рабочей нагрузки. «Бюджет рабочей нагрузки» указывает на то, что пересмотренный бюджет будет сфокусирован в первую очередь, если не исключительно, на сохранении существующих программ и вряд ли будет включать какие-либо новые программные расходы, поскольку опасения по поводу серьезного экономического спада вырисовываются очень сильно.
Это, вероятно, повлияет на январские бюджетные предложения , связанные с подготовкой и наймом учителей, специальным образованием и грантами на возможности , и может даже сократить то, что доступно для формулы финансирования местного контроля и других установленных законом корректировок стоимости жизни.
При бюджете рабочей нагрузки гарантия Предложения 98, хотя и подвержена колебаниям в доходах и зачислении, все же не может быть произвольно уменьшена, но любые новые прогнозы доходов, которые ниже, чем те, которые включены в январский бюджет губернатора, потенциально могут снизить гарантию Предложения 98 в грядущий бюджетный год.
Как сообщает Sacramento Bee , губернатор Ньюсом на пресс-конференции 2 апреля заявил, что «январский бюджет больше не действует. Мир радикально изменился с тех пор, как был предложен январский бюджет, так что все на столе », и что« мы должны быть готовы к существенным корректировкам ».
Законодательный процесс 2020:
Март и апрель, как правило, время, когда политические комитеты (такие как комитеты сената и ассамблеи по образованию) встречаются, чтобы заслушать новые законопроекты, вносимые в их собственные дома.Учитывая продление текущего перерыва в работе Законодательного собрания, крайние сроки для комитета по политике необходимо будет уточнить, когда законодательный орган вернется.
Поскольку законодательный календарь ограничен пандемией COVID-19 и объявлен бюджет рабочей нагрузки из Министерства финансов, возможно, что председатели комитетов по политике предпочтут заслушивать только те законопроекты, которые касаются в первую очередь смягчения последствий вспышки COVID-19 или которые вносят нефискальные корректировки в существующие программы, и, вероятно, откажутся слышать какие-либо предложения по новым программам или новым расходам.
Точно так же, зная, что денег на новые программы, скорее всего, не будет, председатели фискальных комитетов, вероятно, ограничат свои слушания прежде всего мерами, связанными с COVID-19, введенными в их собственных домах. У фискальных комитетов есть крайний срок до 15 мая, чтобы оплатить счета и направить их в свой дом. Крайний срок, когда этажи каждого дома заслушают и проголосуют по законопроектам, внесенным в их дом, и передадут их в другой дом, - 29 мая.
По закону двухлетняя сессия законодательного органа на 2019–2020 годы должна завершиться до полуночи 31 августа.Законодательное собрание может быть созвано на специальные сессии в соответствии с уставными правилами, но текущая сессия не может быть продлена после 31 августа.
Что это означает для законопроектов K-12 и другого законодательства:
Законодательный комитет
CSBA продолжает свою работу на 2020 год по пересмотру нового законодательства и принятию официальных позиций. Комитет встречался дважды в 2020 году (лично в феврале и дистанционно в марте) и занял позицию по более чем 40 новым мерам.
Новые позиции CSBA на 2020 год: утверждены февр.21 | Принят 20 марта
Посмотреть все банкноты 2019–20 годов с позициями CSBA
В настоящее время представляется возможным, что многие законопроекты, по которым Комитет утвердил свою позицию, могут не продвигаться в 2020 году из-за перерыва и общей бюджетной ситуации. Те, которые не продвигаются вперед, скорее всего, будут отложены на год, но могут быть снова представлены в качестве новых законопроектов, когда в январе начнется новая сессия 2021–2022 годов.
Законодательный комитет снова соберется дистанционно в апреле, чтобы продолжить рассмотрение законопроектов, внесенных в 2020 году (все новые законопроекты были представлены до крайнего срока 21 февраля, до начала пандемии COVID-19), гарантируя, что CSBA сохранит официальные позиции по ключевым законопроектам K-12, которые потенциально могут быть продвинуты, когда Законодательное собрание вновь соберется.
Следите за новостями и обновлениями на специальной странице CSBA, посвященной COVID-19.
Аддаббо присоединяется к коллегам из Сената, чтобы обеспечить оставшуюся часть заработной платы по закону семье покойного члена Ассамблеи Квинса Майкла Симановица
Стремясь помочь семье покойного члена Ассамблеи Квинса Майкла Симановица, сенатор штата Нью-Йорк Джозеф П. Аддаббо-младший вместе со своими коллегами из Сената принял закон (S.7428), чтобы предоставить вдове законодателя Дженнифер оставшуюся часть денег. его годовая заработная плата по закону.
«Мы все были глубоко опечалены, когда скончался член парламента Симановиц, и всем сердцем мы сочувствуем его жене и семье», - сказал Аддаббо. «Я считал Майка другом и преданным коллегой-законодателем. Я рад, что Законодательное собрание принимает меры, чтобы протянуть руку помощи Дженнифер и их детям. Хотя ничто никогда не вернет их любимых мужа и отца, этот закон, по крайней мере, обеспечит семье Майка некоторую финансовую поддержку ».
Симановиц, скончавшийся в сентябре в возрасте 45 лет, оставил после себя жену и четверых детей.Семья получит сумму, которая представляет собой то, что член Собрания заработал бы в Законодательном собрании с момента его смерти до конца 2017 года. Подобные законопроекты были одобрены в прошлом для семей законодателей, которые скончались во время пребывания в должности.
Закон также был одобрен Собранием штата и теперь будет отправлен на рассмотрение губернатору Куомо.
S7428
Относится к выделению средств на оплату труда Дженнифер Симановиц, вдовы покойного Майкла А.Симановиц, член Ассамблеи, остаток причитающейся ему невыплаченной годовой компенсации за часть 2017 года
- Представлено
- В Комитете
- Настольный календарь
- Прошло Сенат
- Прошло собрание
- Передано губернатору
- Проверено губернатором
13 февраля 2018 г.
Нарушено вето губернатором
facebook
твиттер
Эл. адрес
Бывший спикер Ассамблеи Нью-Йорка Шелдон Сильвер освобожден из тюрьмы: отчет
Бывший спикер Ассамблеи Нью-Йорка Шелдон Сильвер (D) освобожден из тюрьмы в отпуск, сообщил источник Associated Press.
Сильвер был отпущен к себе домой, поскольку он ожидает окончательного решения о том, сможет ли он отбыть оставшийся срок в домашнем заключении.
Сильвер, 77 лет, начал отбывать более шести лет лишения свободы по обвинению в коррупции в федеральной тюрьме в Отисвилле, штат Нью-Йорк, в августе, сообщает AP.
Приговор стал третьим для Сильвера после того, как предыдущие обвинительные приговоры в отношении бывшего спикера были частично или полностью отменены по апелляции, что позволило ему избежать тюрьмы.
Представитель U.Прокуратура С. на Манхэттене, которая преследовала Сильвера, сообщила AP, что в понедельник она направила в Управление тюрем электронное письмо, в котором выразила несогласие с увольнением Сильвера.
В заявлении для The Hill бюро сообщило: «Из соображений конфиденциальности, безопасности и защиты мы не обсуждаем планы освобождения заключенных».
AP отметило, что Конгресс расширил полномочия Министерства юстиции в условиях пандемии коронавируса, позволив заключенным быть освобожденным в отпуск и домашнее заключение, чтобы предотвратить распространение COVID-19 в тюрьмах.
В мае прошлого года Майкл КоэнМайкл Дин КоэнАвтор скандального досье на Трамп в России высказывается: «Я поддерживаю проделанную нами работу» Трамп-организация сталкивается с новым вниманием в ходе гражданского расследования в Нью-Йорке Майкл Коэн: Трамп блефует по поводу еще одной заявки Белого дома БОЛЬШЕ, бывший президент ТрампДональд ТрампРеспубликанцы готовы покорить Вирджинию, ошеломляя демократов Пять выводов из мрачной ночи для демократов Гонка губернатора Нью-Джерси слишком близка, чтобы позвонить бывшему адвокату МОРЕ, были освобождены из того же учреждения в Отисвилле, что соответствовало усилиям Министерства юстиции сократить количество заключенных в тюрьмах в условиях пандемии.
Бюро тюрем также сообщило, что иногда оно переводит заключенных в их дома на периоды времени, в то время как они считаются помещенными в дом или помещением в приют для временного содержания.
The Hill обратилась за комментариями в федеральную тюрьму Отисвилля и в прокуратуру США на Манхэттене.
Сильвер был спикером Ассамблеи Нью-Йорка более 20 лет, прежде чем был осужден в 2015 году за получение незаконных платежей на сумму почти 4 миллиона долларов в обмен на услуги.
Он был вовлечен в схемы, связанные с развитием недвижимости, и его обвинили в участии в заговоре с участием исследователя рака из Колумбийского университета.
В январе Верховный суд отклонил ходатайство Сильвера о рассмотрении апелляции на его приговор.
Серебро, по слухам, рассматривалось как вопрос о помиловании в последнюю минуту от Трампа, но такого помилования не было.
—Обновлено в 16:44
Лидер Сената Стюарт-Казинс представляет остаток законодательной сессии штата Нью-Йорк
Во вторник лидер Сената штата Нью-Йорк представил обзор оставшихся недель законодательной сессии.
Демократический лидер Сената штата Нью-Йорк Андреа Стюарт-Казинс начала виртуальный брифинг, повторив чувства президента Джо Байдена, который сказал, что «молится, чтобы вердикт был правильным» на суде над бывшим офицером полиции Миннеаполиса Дереком Човеном. Присяжные заседали по делу после смерти Джорджа Флойда в мае прошлого года.
«Все немного встревожены, поскольку мы ждем результатов суда. Я знаю, как семья и все знают, Джорджа Флойда, что бы ни случилось, истинного правосудия не может быть», - сказала она.
После того, как присяжные признали Шовена виновным по всем трем обвинениям во вторник днем, Стюарт-Казинс опубликовала следующее заявление.
«Хотя я воодушевлен этим вердиктом и считаю, что это важный шаг на пути к ответственности, мы должны помнить, что этот вердикт не является истинным правосудием», - сказал Стюарт-Казинс. "Истинная справедливость означала бы, что Джордж Флойд ушел бы от этой встречи живым. Это означало бы, что он мог бы наблюдать, как растет его дочь. Если бы у нас была настоящая справедливость в этой стране, которая соответствует нашим идеалам, бесчисленное множество других чернокожих мужчин и женщин не постигла бы судьба Джорджа Флойда.Хотя мы не можем изменить прошлое, мы можем изменить то, что произойдет дальше. Мы можем решить, что больше не можем терпеть систему охраны правопорядка и систему правосудия, которая служит только некоторым, а не всем. Мы можем посвятить себя реальным реформам, подлинному правосудию и более совершенной системе охраны правопорядка, которая действительно защищает наши сообщества, а не разрывает их на части. Мои мысли связаны с семьей Флойд и семьями в основном чернокожих и коричневых по всей стране, которые потеряли любимого человека в результате полицейского насилия ».
По другим вопросам Стюарт-Казинс говорит, что новая система, с помощью которой законодательный орган наблюдает за полномочиями губернатора Эндрю Куомо на случай пандемии, работает.
Демократа из Вестчестера спросили о надзоре за декларациями обеспокоенного губернатора COVID-19 после того, как в прошлом месяце законодатели отменили чрезвычайные полномочия.
«Часть того, что губернатор должен сделать из-за возврата чрезвычайных полномочий, - это своевременно предупреждать комитеты и предупреждать нас о различных изменениях, которые он вносит, что он и сделал», - сказала она.
Законодательный орган предоставил губернатору Куомо чрезвычайные полномочия для борьбы с пандемией в 2020 году.
Стюарт-Казинс говорит, что теперь, когда государственный бюджет исчерпан, она ожидает напряженного завершения законодательной сессии. Это произошло после того, как законодатели легализовали рекреационную марихуану и мобильные ставки на спорт в пакет расходов. Стюарт-Казинс говорит, что на ее конференции еще не обсуждался законопроект о здравоохранении с единым плательщиком, который одобряют прогрессисты в Олбани.
«Я уверена, что с сегодняшнего дня до июня, когда мы откроемся на лето, будет очень напряженный период», - сказала она.
Стюарт-Казинс говорит, что, учитывая множество обвинений в преследовании губернатора Куомо и вопросы о публикации его мемуаров о пандемии в прошлом году, Сенат также может рассмотреть новые реформы этики.
«Мы говорили о реформах этики и рассматривали некоторые возможности и вносили изменения в J-COPE, и мы всегда стремимся усилить подотчетность и прозрачность, поэтому вы можете быть уверены, что мы уже начали проводить эти talkatiosn, и мы продолжим эти разговоры, и я верю, что есть аппетит к этике, как и ко всему остальному, всегда есть аппетит к укреплению различных частей, которые, очевидно, необходимо усилить », - сказала она.
Стюарт-Казинс, которая призвала губернатора Куомо уйти в отставку, говорит, что она не обсуждала с губернатором план завершения заседания.
«Я не разговаривал с губернатором по поводу конкретной законодательной повестки дня, но мы будем двигаться, и мы продолжим работать с нашими партнерами, Ассамблеей и так далее, а также вносить изменения в законодательство по своему усмотрению», она сказала.
Поскольку надежды Куомо на четвертый срок потенциально уменьшились, лидера Сената также спросили, сможет ли она баллотироваться на пост губернатора в 2022 году.