Студентам с вопросами о лабораторных работах сюда

Тема в разделе "WASM.BEGINNERS", создана пользователем IceStudent, 11 ноя 2006.

  1. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.792
    А зачем так сложно? Для чего "мучить" системную дату, а потом восстанавливать ее?
    Узнать по дате день недели (формула вечного календаря) можно так
    W = d + [ (13m - 1) / 5 ] + y + [ y / 4 ] + [ c / 4 ] - 2c
    где d - число месяца; m - номер месяца, начиная с марта (март=1, апрель=2, ... февраль=12);
    y - номер года в столетии (например, для 1965 года y=65. Для января и февраля 1965 года, т.е. для m=11 или m=12 номер года надо брать предыдущий, т.е. y=64);
    c - количество столетий (например, для 2000 года c=20. И здесь для января и февраля 2000 года надо брать предыдущее столетие с=19);
    квадратные скобки означают целую часть полученного числа (отбрасываем дробную).
    Результат W делите на 7 и остаток от деления даст день недели (воскресенье=0, понедельник=1, ... суббота=6)
    Пример: для 31 декабря 2008 года определяем: d=31, m=10, y=8, c=20
    По формуле находим: W = 31 + [ ( 13 * 10 - 1 ) / 5 ] + 8 + [ 8 / 4 ] + [ 20 / 4 ] - 2 * 20 =
    = 31 + 25 + 8 + 2 + 5 - 40 = 31
    Теперь делим W на 7 и находим остаток от деления: 31 / 7 = 4 и 3 в остатке. Тройка соответствует дню недели СРЕДА.
    (с) Энциклопедия для детей, том 11, Математика, с.159
     
  2. Oliger

    Oliger New Member

    Публикаций:
    0
    Регистрация:
    7 янв 2010
    Сообщения:
    2
    кто может сделать эту задачу? 30 вмз за код
     
  3. evgeni_nik1

    evgeni_nik1 New Member

    Публикаций:
    0
    Регистрация:
    12 янв 2010
    Сообщения:
    1
    Люди добрые помогите! Задачка простая, но я в этом полный 0! Нужно разработать программу на языке ассемблер (486) выполняющую поиск максимального нечетного элемента в массиве (операнды разместить в СД). ПОМОГИТЕ!
     
  4. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    т.к. ни компилятор, ни режим, ни размер элементов не указан, вот общий случай для 486 процессора в 32-х битном режиме. операнды помещаются в стек в следующем порядке
    Код (Text):
    1. push номер максимального элемента
    2. push размер элемента
    3. push размер массова
    4. push указатель на массив
    Код (Text):
    1. mx:
    2.   pushf
    3.   pusha
    4.   mov ebx, [esp+40];указатель на массив элементов
    5.   mov ecx, [esp+44];количество элементов в массиве
    6.   jecxz ex;массив пуст
    7.   xor ebp, ebp
    8.   std;флаг направления просмотра (от конца к началу)
    9. l0:
    10.    push ecx
    11.    test byte [ebx], 1;если элемент четный - пропустить
    12.    jz no
    13.     test ebp, ebp;максимальный элемент еще не выбран - сделать i-ый элемент максимальным
    14.     jz ok
    15.      mov ecx, [esp+52];длина элемента
    16.      lea esi, [ebx+ecx-1];последний байт энного элемента массива
    17.      lea edi, [ebp+ecx-1];последний байт максимального элемента массива
    18. nx:
    19.      repz cmpsb;сравнить i-ый с максимальным
    20.      jb no;i-ый меньше максимального - пропустить
    21.      jz el;i-ый равен максимальному - посчитать
    22. ok:
    23.       mov ebp, ebx;сделать i-ый элемент максимальным
    24.       xor edx, edx;сбросить счетчик максимальных элементов
    25. el:
    26.       inc edx;посчитать найденный максимальный элемент
    27. no:
    28.    pop ecx;перейти к следующему элементу
    29.    add ebx, [esp+48];длина элемента
    30.   loop l0
    31.   cmp edx, [esp+52];номер требуемого максимального элемента
    32.   jnz ex
    33.    mov [esp+28], ebp;вернуть указатель на максимальный элемент
    34. ex:
    35.   popa
    36.   popf
    37.   ret
    следующий код ищет 2-е вхождение максимального элемента в массив из 10-и 4-х байтных элементов
    Код (Text):
    1. push 2
    2. push 4
    3. push 10
    4. push ar
    5. call mx
    6. ;где ar объявляется как
    7. ar   dd 4,5,6,5,7,5,3,7,7,8
    p.s. опечатки ищите сами
     
  5. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    для знаковых элементов поменять
    Код (Text):
    1. jb no;i-ый меньше максимального - пропустить
    на
    Код (Text):
    1. jl no;i-ый меньше максимального - пропустить
     
  6. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    Всем привет, народ, пожалуйста помогите бедному студенту сделать задачу, очень прошу :rolleyes: Сам нифига в асм'е не понимаю, точнее общие комманды, а вот самому не написать.
    Надо написать программу win32 на tasm.

    вот условие:
    "Есть файл - каталог файлов. Занесите в отдельный файл записи о файлах, созданных ранее указанной даты."

    Если можно то как можно проще. Надеюсь на вашу помощь. Спасибо.
     
  7. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    1. открываем файл для чтения
    push 0 ; шаблон также не требуется
    push 0 ; атрибуты для открываемого файла указывать не требуется
    push OPEN_EXISTING ; 3 (если не ошибаюсь)
    push 0 ; lpSecurityAttributes = NULL
    push 0 ; ShareMode=FILE_SHARE_NONE другим программам доступа не будет
    push GENERIC_READ ; 40000000h (если не ошибаюсь)
    push offset wSourceFileName ; что-то вроде wSourceFileName db 'F', 0, 'i', 0, 'l', 0, 'e', 0, '.', 0, 't', 0, 'x', 0, 't', 0, 0, 0
    call CreateFileW ; вызов функции открытия файла

    (далее подобные вызовы будут оформляться так call CreateFileW, offset wSourceFileName, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)

    2. открываем файл для записи
    call CreateFileW, offset wResultFileName, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0

    3. если при открытие в eax число отличное от INVALID_HANDLE_VALUE, то запоминаем его для последующих вызовов скажем в регистре/ячейке памяти. в данном случае хватит и регистров

    4. выделяем файл под буфер
    на выбор
    или call GlobalAlloc, GPTR, buffer_size/mov pBuffer, eax (для освобожения call GlobalFree, pBuffer)
    или call GetProcessHeap/call HeapAlloc, eax, HEAP_ZEROMEMORY, buffer_size/mov pBuffer, eax (для освобожения call GetProcessHeap/call HeapFree, eax, HEAP_ZEROMEMORY, pBuffer)
    или call VirtualAlloc, 0, (buffer_size + 4095) and (not 4095), MEM_COMMIT, PAGE_READWRITE/mov pBuffer, eax (для освобождения call VirtualFree, pBuffer, (buffer_size + 4095) and (not 4095), MEM_DECOMMIT)
    или просто резервируем место в стеке (sub esp, buffer_size/mov pBuffer, esp, для освобождения add esp, buffer_size)
    или просто резервируем место в секции не инициированных данных (db buffer_size dup (0), освобождения не требует)

    5. читаем в буфер из файла
    call ReadFile, hSource, pBuffer, buffer_size, esp, 0
    (для тех кому данный вариант не по вкусу могу предложить также
    lea eax, [esp-4]/call ReadFile, hSource, pBuffer, buffer_size, eax, 0, 0/pop edx)

    6. пишем в файл
    call WriteFile, hResult, pBuffer, buffer_size, esp, 0
    (для тех кому данный вариант не по вкусу могу предложить также
    lea eax, [esp-4]/call WriteFile, hResult, pBuffer, buffer_size, eax, 0, 0/pop edx)

    7. закрываем файлы
    call CloseHandle, hFile (где hFile это либо hResult, либо hSource)

    8. сравниваем даты
    тут все сложнее. зависит от формата. опишите подробнее. из общих советов: сравнивается сначала год, потом месяц, затем день, час, минут и т.д.

    примерный алгоритм
    открыть файл для чтения
    cmp eax, INVALID_HANDLE_VALUE
    jz error0
    mov esi, eax ;hSource equ esi
    открыть файл для записи
    cmp eax, INVALID_HANDLE_VALUE
    jz error1
    mov edi, eax ;hResult equ edi
    выделить память под буфер
    test eax, eax
    jz error2
    mov ebx, eax ;pBuffer equ ebx
    next:
    считать данные в буфер
    cmp edx, buffer_size
    jc done
    сравнить дату
    jae next
    записать данные в файл
    jmp next
    done:
    освободить память pBuffer(ebx)
    error2:
    закрыть файл hResult(edi)
    error1:
    закрыть файл hSource(esi)
    error0:
    ret
     
  8. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    прошу прощения. забыл поправить

    2. открываем файл для записи
    call CreateFileW, offset wResultFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0
     
  9. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    2 max7C4, ну для начала хотел бы сказать спасибо за оказание помощи ;)
    а вот по поводу пункта 8: не стоит доходить до минут)) думаю вариант только с датой прокатит, ну максимум еще год добавить.
    в пункте 4 - первый вариант, вроде более компактен))
    в пунктах 5,6 - более понятен первый вариант, а не тот что в скобках

    Огромная просьба: можно ли это как то объединить в общий один файл, который сразу можно компилировать? пожалуйста=)
     
  10. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Benzin
    в пункте 4 самым компактным является 4 вариант, а самым простым в реализации вариант номер 5
    в пунктах 5 и 6 в скобках дан более корректный вариант т.к. в первом мы пользуемся тем моментом, что АПИ сначала проверяет указатель на 0, а только потом на его место записывает количество прочитанных/записанных байт. это в любой момент может измениться и придется использовать вариант в скобках. в скобках приводится вариант из 3 отдельных строчек
    если разбить его на отдельные компоненты, и прокомментировать, то получится следующее
    lea eax, [esp-4]; вычисляет адрес переменной относительно текущего положения стека
    push 0; инициировать локальную (временную) переменную 0
    push 0; lpOverlapped = NULL
    push eax; указатель на переменную созданную двумя строчками выше (хотя ее адрес я посчитал еще до создания)
    push buffer_size;количество байт для чтения/записи
    push pBuffer;указатель на буфер для данных
    push hFile;дескриптор открытого файла
    call Function; указатель на функцию чтения/записи в файл
    pop edx;освобождение памяти из под переменной (автоматически в регистр edx записывается количество реально прочитанных/записанных байт)

    в первом же случае вместо eax передается esp и тем самым последний параметр (lpOverlapped) принимает роль этой переменной, хотя лучше бы так не делать!
     
  11. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    достаточно взять шаблон PE файла из примеров поставить в секцию кода примерно расписанный алгоритм программы и заменить русские строки аналогичными записями из предшествующих 8 пунктов.
    так же на счет формата хранения даты создания файла я ничего не понял. ее можно хранить по разному. начиная от текстовой формы (как на ISO дисках) так в системной (структура SYSTEM_TIME) или вообще файловой (мне известно как минимум 4, а может и 5, форматов хранения даты в файловых записях)
     
  12. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    к тому же я привожу вариант работы с файлом из записей фиксированной длины, хотя это может быть и не так. тогда алгоритм работы с таким файлом несколько (не сильно) видоизменится.
     
  13. Benzin

    Benzin Сергей

    Публикаций:
    0
    Регистрация:
    26 авг 2007
    Сообщения:
    41
    Адрес:
    St.Petersburg
    ткните носом, где его взять)
    эээм, как все сложно, а какой самый простой, просто ассемблеры у нас были недолго, как раз в конце я уже не ходил на них, но изучали все поверхностно, особенно win32, так что особых выкрутасов не было
     
  14. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    что-то вроде этого
    Код (Text):
    1. .386
    2. .model flat,stdcall
    3. .stack 1048576
    4. extern CreateFileW:NEAR
    5. extern APIName:NEAR;APIName - заменишь на CloseHandle etc (см. строчкой выше)
    6. includelib c:\tasm5\lib\import32.lib
    7. buffer_size equ 1024
    8. .code
    9. main proc
    10. открыть файл для чтения
    11. cmp eax, INVALID_HANDLE_VALUE
    12. jz error0
    13.   mov esi, eax ;hSource equ esi
    14.   открыть файл для записи
    15.   cmp eax, INVALID_HANDLE_VALUE
    16.   jz error1
    17.    mov edi, eax ;hResult equ edi
    18.    выделить память под буфер
    19.    test eax, eax
    20.    jz error2
    21.     mov ebx, eax ;pBuffer equ ebx
    22. next:
    23.     считать данные в буфер
    24.     cmp edx, buffer_size
    25.     jc done
    26.      сравнить дату
    27.      jae next
    28.       записать данные в файл
    29.       jmp next
    30. done:
    31.     освободить память pBuffer(ebx)
    32. error2:
    33.    закрыть файл hResult(edi)
    34. error1:
    35.   закрыть файл hSource(esi)
    36. error0:
    37.  ret
    38. main endp
    39. .data
    40. buffer db buffer_size dup (0)
    41. end main
    тоды берите SYSTEM_TIME. 8 dw переменных подряд. wYear,wMonth,wDayOfWeek,wDay,wHour,wMinute,wSecond,wMilliseconds

    cmp ebx[time.wYear], 0
    jae next
    cmp ebx[time.wMonth], 1
    jae next
    cmp ebx[time.wDay], 1
    jae next
    cmp ebx[time.wHour], 0
    jae next
    cmp ebx[time.wMinute], 0
    jae next
    cmp ebx[time.wSeconds], 0
    jae next
    cmp ebx[time.wMilliseconds], 0
    jae next

    все которые созданы раньше 1 января 0 года н.э.
     
  15. Patriot86rus

    Patriot86rus New Member

    Публикаций:
    0
    Регистрация:
    5 фев 2010
    Сообщения:
    6
    max7C4
    Сердечно благодарен за код!!!...
     
  16. Patriot86rus

    Patriot86rus New Member

    Публикаций:
    0
    Регистрация:
    5 фев 2010
    Сообщения:
    6
    max7C4
    Пусть буду до конца не грамотным, но может напишешь как компилировать..у меня вот Win 7 стоит х64
     
  17. Patriot86rus

    Patriot86rus New Member

    Публикаций:
    0
    Регистрация:
    5 фев 2010
    Сообщения:
    6
    От и до..начиная с копирования кода..))))!
     
  18. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    Patriot86rus
    1. ОС к этому не имеет ровным счетом ни какого отношения.
    2. тот код что я написал должны проглотить masm или tasm, но оформление которое было опущено должно быть добавлено различное для каждого из компиляторов (судя по всему, среди преподавателей пока очень популярны эти два, вот на это я и рассчитывал)
    3. если можно, то уточните задание т.к. приведенный код возможно очень не точен.
     
  19. Patriot86rus

    Patriot86rus New Member

    Публикаций:
    0
    Регистрация:
    5 фев 2010
    Сообщения:
    6
    max7C4
    Задание было:
    Написать программу, которая за определенный интервал времени показывает Вашу фамилию заданное количество раз через равномерные промежутки времени.
    Обработчик прерывания: таймер
     
  20. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    ну примерно так
    Код (Text):
    1. .386
    2. .model small
    3. .stack 400h
    4. .data                                          ; секция данных (256 байт)
    5.  delay               dd 0                    ; интервал между выводами текста
    6.  times               dd 0                    ; количество выводов текста
    7.  ticks                dd 0                    ; количество тиков таймера
    8.  FIO_Buffer        db 244 dup (0)      ; буфер
    9. .code                                         ; секция кода
    10. main:                                          ; основная подпрограмма
    11.                                                  ; настраиваем вектор прерывания 8 на эту программу
    12.  xor ax, ax                                   ; в сегментe 0 (ds=0)
    13.  mov ds, ax
    14.  mov bx, 8*4                                ; по смещению 8*4=32
    15.  mov ax, offset irq8                       ; записываем offset irq8, cs
    16.  mov dx, cs
    17.  cli
    18.  xchg [bx+0], ax
    19.  xchg [bx+2], dx
    20.  sti
    21.  mov word ptr cs:timer[0], ax          ; старые значения сохраняем в переменной timer
    22.  mov word ptr cs:timer[2], dx
    23. ; настраиваем сегментный регистр ds на сегмент данных (ds=@Data)
    24.  mov bx, @Data
    25.  mov ds, bx
    26. ; вводим интервал
    27.  mov dx, offset mes0
    28.  call sub0
    29.  push offset FIO_Buffer
    30.  call sub1
    31.  jc quit
    32.  mov delay, eax
    33. ; вводим количество
    34.  mov dx, offset mes1
    35.  call sub0
    36.  push offset FIO_Buffer
    37.  call sub1
    38.  jc quit
    39.  test eax, eax
    40.  jz quit
    41.  mov times, eax
    42. ; вводим фамилию
    43.  mov dx, offset mes2
    44.  call sub0
    45.  mov FIO_Buffer[bx-2], '$'
    46. ; цикл вывода текста
    47. next_time:
    48.  mov eax, delay                       ; ждем пока переменная ticks не вырастет на delay*18 тиков
    49.  mov edx, eax
    50.  add edx, edx                          ; edx*2
    51.  shl eax, 4                              ; eax*16
    52.  add eax, edx                          ; eax*18
    53.  add eax, ticks                        ; eax*18+ticks
    54.                                             ; ждем
    55. wait:
    56.  hlt
    57.  cmp ticks, eax
    58.  jb wait
    59.                                            ; выводим фамилию
    60.  mov dx, offset FIO_Buffer
    61.  mov ah, 9
    62.  int 21h
    63.                                            ; если фамилия выведена меньше times раз, то повторяем
    64.  dec times
    65.  jnz next_time
    66.  
    67. quit:                                     ; ждем нажатия клавиши
    68.  xor ax, ax
    69.  int 16h
    70.                                            ; восстанавливаем значение irq8 (ds=0; bx=8*4=32)
    71.  mov ax, word ptr cs:timer[0]
    72.  mov dx, word ptr cs:timer[2]
    73.  xor bx, bx
    74.  mov ds, bx
    75.  mov bx, 8*4
    76.  cli
    77.  mov [bx+0], ax
    78.  mov [bx+2], dx
    79.  sti
    80.                                            ; выход (exitcode=0)
    81.  mov ax, 04C00h
    82.  int 21h
    83.  
    84. sub0:                                   ; подпрограмма 0 (ввод строки с выводом запроса, DOS 09h+40h) in [dx=offset message] out [FIO_Buffer=string; bx=количество введенных символов]
    85.  mov ah, 9                             ; вывод сообщения
    86.  int 21h
    87.  mov ah, 40h                         ; ввод строки
    88.  xor bx, bx
    89.  mov cx, 244
    90.  mov dx, offset FIO_Buffer
    91.  int 21h
    92.  mov bx, ax                            ; установка завершающего 0 вместо 13 и 10
    93.  mov word ptr FIO_Buffer[bx-2], 0
    94.  ret
    95.  
    96. sub1:                                   ; подпрограмма 1 (перевод строки в число) in [par0 = new offset string] out [eax=число]
    97.  push bp
    98.  mov bp, sp
    99.  mov si, [bp+4]                      ; ds:si = строка
    100.  xor edx, edx                         ; result=0
    101.  xor eax, eax
    102. next_char:
    103.  lodsb
    104.  test al, al                             ; if [ds:si+i]==0 done
    105.  jz done
    106.  sub al, 48
    107.  jc error
    108.  cmp al, 9
    109.  ja error
    110.  mov ecx, edx                         ; result=result*10+[ds:si+i]-'0'
    111.  add edx, edx; edx*2
    112.  jc error
    113.  add edx, edx; edx*4
    114.  jc error
    115.  add edx, ecx; edx*5
    116.  jc error
    117.  add edx, edx; edx*10
    118.  jc error
    119.  add edx, eax; edx*10+eax
    120.  jnc next_char
    121. error:
    122.  xor edx, edx
    123.  stc
    124. done:
    125.  mov eax, edx
    126.  pop bp
    127.  ret
    128. ; обработчик прерывания от таймера данной программы (увеличивает значение переменной ticks)
    129. irq8:
    130.  push ds
    131.  push @Data
    132.  pop ds
    133.  inc dword ptr ds:ticks
    134.  pop ds
    135. timer=$+1                      ; чтобы не объявлять лишних переменных переменная timer расположена по тому же адресу, что и инструкция процессора длинного перехода на этот самый адрес
    136.  jmp 0:0
    137.  
    138. mes0     db 'Введите интервал между выводами текста: $'
    139. mes1     db 'Введите количество выводов текста: $'
    140. mes2     db 'Введите фамилию: $'
    141. end main
    если не изменяет память, то компилируется это так
    tasm asm_file.asm или masm asm_file.asm
    tlink asm_file.obj или link asm_file.obj

    опечатки ищите сами