#assembly #dos #unix-timestamp #x86-16
#сборка #dos #unix-временная метка #x86-16
Вопрос:
Как я могу получить текущее время UNIX на 8086 asm? Я не смог найти никакой информации в Интернете. Я знаю, что это 32 бит, поэтому ему пришлось бы заполнить 2 регистра. РЕДАКТИРОВАТЬ: операционная система — DOS (я использую Dosbox)
Комментарии:
1. Если ваша операционная система не Xenix, ответ таков: вы не можете. Вам нужно будет получить дату и время в любом формате, предоставляемом вашей операционной системой, а затем преобразовать их во время Unix.
2. Для какого UNIX вы программируете?
3. Затем вы можете получить y / m / d time и использовать ответ Мартина, чтобы преобразовать это для преобразования во время Unix по модулю високосных секунд.
Ответ №1:
Как я могу получить текущее … время на 8086 asm?
Вопрос в том: «Какую операционную систему вы используете?»
У процессора нет никаких часов реального времени. И даже на ранних компьютерах x86 ее не было. Операционная система (или BIOS) знает, как получить системное время.
Как я могу получить текущее время UNIX на 8086 asm?
Если ваша операционная система не поддерживает время UNIX, но она поддерживает время, указанное как «дата» (Y, M, D, h, m, s), есть только сложный способ:
Здесь псевдокод:
; Calculate the number of days from 1970/1/1 to 1/1 of this year
; not including the 29ths of February
time = (year-1970)*365
; Calculate the number of 2/29s (leap years) passed since
; 1970/1/1 until today (including 2/29 of this year if this
; year is a leap year!)
leapyears = year-1969
if month > 2:
; It is March or later; the 29th of February (if any)
; has already passed this year.
leapyears = leapyears 1
end-if
; Here "leapyears" has the following value:
; 1970: 1 or 2 => x/4 = 0
; 1971: 2 or 3 => x/4 = 0
; 1972: 3 or 4 => x/4 = 0 or 1
; 1973: 4 or 5 => x/4 = 1
; ...
; 2019: 50 or 51 => x/4 = 12
; 2020: 51 or 52 => x/4 = 12 or 13
; 2021: 52 or 53 => x/4 = 13
; ...
; This is a division by 4. You can do it using two SHR 1
; instructions: "SHR register, 1"
leapyears = leapyears SHR 2
; Add the result to the number of days from 1970/1/1
; until today
time = time leapyears
; Look up the number of days from 1/1 of this year until
; the 1st of this month; not including 2/29 (if any)
; You could do this the following way:
; LEA BX, lookupTable
; ADD BX, month (in a 16-bit register)
; MOV AX, [BX]
; Or:
; LEA BX, lookupTable
; ADD BL, month (in an 8-bit register)
; ADC BH, 0
; MOV AX, [BX]
yearDays = lookupTable[month]
; And add this number to the number of days
time = time yearDays
; Add the day-of-month to the number of days since 1970/1/1
time = time dayOfMonth - 1
; Convert days to seconds (note: We assume: No leap seconds)
; and add hours, minutes and seconds (note: We assume: GMT time zone)
time = 24 * time
time = time hours
time = 60 * time
time = time minutes
time = 60 * time
time = time seconds
---
lookupTable:
0 # illegal
0 # Days between 1/1 and 1/1
31 # Days between 2/1 and 1/1
31 28 # Days between 3/1 and 1/1
31 28 31 # Days between 4/1 and 1/1
...
Я уверен, что вы сможете преобразовать псевдокод в ассемблерный — если вам действительно нужно это сделать.
Комментарии:
1. Современные процессоры x86 действительно имеют 64-разрядный TSC (счетчик временных меток), который является разновидностью часов реального времени (с функциями nonstop_tsc и invariant_tsc). Однако он отсчитывает время настенных часов с момента последнего сброса, а не абсолютное время. (И подсчитывается в тактах, длина / частота которых зависит от модели процессора.) При правильном масштабировании / смещении калибровки вы можете сопоставить TSC с абсолютным временем реального времени, таким как время Unix. На процессоре с тактовой частотой 4 ГГц для завершения TSC требуется ~ 146 лет (
2^64 / (4*10^9) / (3600*24*365.25)
), что дольше, чем 32-разрядные секунды Unix.2. Я думаю, вам также понадобится таблица подстановки, для которой годы имели високосные секунды, если вы хотите строгой точности.