(DS:SI) -> (ES:DI): в отладчике работает, в бою-нет?

Тема в разделе "WASM.BEGINNERS", создана пользователем _mm_, 28 дек 2010.

  1. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    Всем здравствуйте.
    К сожалению, пока я здесь новичок, поэтому, возможно, написал сообщение не в соответствующий раздел (но этот показался мне самым подходящим). Перво-наперво, конечно, хотелось познакомиться с людьми, изучающими asm, не только с "бывалыми", но и новичками. Хотелось бы не только просить, но и в чём-то помогать, правда, пока я мало на что сгожусь.
    Это было предисловие, а вот собственно вопрос. Начал изучать ассемблер по книге Калашникова, но это мне показалось недостаточным. К концу темп в его рассылке серьёзно ускоряется, поэтому я сам себе задаю усложнённые промежуточные примеры. В одном из них - в отладчике программа работает прекрасно, но в деле никак. Вот задача.

    а). Программа hello.com выводит строку "Hello, world!". Я хочу создать другую программу-патч, которая исправила бы com-файл, а точнее строчку "Hello, world!" на "Goodbye, world".

    Вот текст первой программы, помещаемой в каталог с нашей под именем hello.com (её объяснять не надо):
    Код (Text):
    1. CSEG segment
    2. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
    3. org 100h
    4. Begin:
    5.     mov ah,9
    6.     mov dx,offset Message
    7.     int 21h
    8.     int 20h
    9. Message db 'Hello, world!$'
    10. CSEG ends
    11. end Begin
    Моя логика была следующая. Строка "Hello, world!" в com-файле находится по адресу, на 9h больше, чем начало (100h). Я "закину" программу в конец своей, исправлю там строчку, и снова запишу (с использованием rep movb).
    Вот её код.

    Код (Text):
    1. .286
    2.  
    3. CSEG segment
    4. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
    5. org 100h
    6.  
    7. begin:
    8.  
    9. ;Данная программа будет обновлять файл
    10. ;hello.com
    11.  
    12. ;Первоначально откроем файл RW
    13. mov ax,3D02h
    14. mov dx,offset File_name
    15. int 21h
    16. jc Message_bad
    17.  
    18. ;Если файл существует, сохраняем номер файла
    19. mov Handle,ax
    20. mov bx,ax
    21.  
    22. ;Чтение в память
    23. mov ah,3Fh
    24. ;Определяем количество читаемых байт (напр. 65000)
    25. mov cx,0FDE8h
    26. ;По адресу памяти за нашей программой
    27. mov dx,offset Finish
    28. int 21h
    29.  
    30.  
    31. ;Файл в нашей памяти. Строка Hello, world находится в db
    32. ;в смещении 109h от начала программы hello, т.е. через 9 байт
    33. ;У нас она располагается тоже через 9 байт, но после конца (Finish equ $)
    34. ;Определим её настоящий адрес
    35.  
    36. add dx,9h
    37.  
    38. ;Переносим 15 букв c адреса смещения переменной New_phrase
    39. ;на новый адрес dx (конец нашей програмы + 9 байт)
    40.  
    41. mov si,offset New_phrase
    42. mov di,dx
    43. mov cx,15
    44. rep movsb
    45.  
    46. ;Смотрим отладчик - файл прочтён и строка в памяти заменилась!
    47.  
    48. ;Подпрограмма успешного вывода строки и выхода
    49. Message_ok:
    50. ;Сначала сохраним файл, восстановив bx
    51. mov bx,Handle
    52. mov ah,3Eh
    53. int 21h
    54. ;Выводим строку
    55. mov ah,9
    56. mov dx,offset Mess_ok
    57. int 21h
    58. int 20h
    59.  
    60. ;Подпрограмма безуспешного вывода строки и выхода
    61. Message_bad:
    62. mov ah,9
    63. mov dx,offset Mess_bad
    64. int 21h
    65. int 20h              
    66.  
    67. ;Имя файла
    68. File_name db 'hello.com',0,'!$'
    69.  
    70. ;Успешное сообщение
    71. Mess_ok db 'Файл обновлён. Всем спасибо.$'
    72.  
    73. ;Плохое сообщение
    74. Mess_bad db 'Файл не найден. Поместите hello.com в каталог с программой.$'
    75.  
    76. ;Определяем переменную
    77. Handle dw 0FFFFh
    78.  
    79. ;Новая фраза, которая заменяет Hello, world
    80. New_phrase db 'Goodbye, world!$'
    81.  
    82. ;Переменная для вычисления длины файла
    83. Finish equ $
    84.  
    85. CSEG ends
    86. end begin
    Всё бы ничего, но программа ничего не меняет, в отладчике меняется прекрасно, ошибок записи в ax не выводит. Да и это легко проверить, например, заменю код

    Код (Text):
    1. mov si,offset New_phrase
    2. mov di,dx
    3. mov cx,15
    4. rep movsb
    на другой, который добавляет в самый конец цифру "1" к файлу hello.com:

    Код (Text):
    1. mov ah,40h
    2. mov dx,offset addFile1
    3. mov cx,1
    4. int 21h
    Разумеется, в конец нашего файла также кидаем

    Код (Text):
    1. addFile1 db '1'
    К файлу hello.com добавляется в конец цифра 1 - то есть с остальной частью всё в порядке?
    Почему же в памяти программа меняет текст, а в файл не записывает, хотя сохранение hello.com отрабатывает без ошибок?
    Спрашивал всех знакомых программистов, никто не может подсказать.
    В поиске ответа не нашёл. Также, этот вопрос, как я понимаю, не подпадает под тему "Лабораторная работа".
    Ещё раз извиняюсь, если не туда отписался (просто удалите сообщение, если что не так).
     
  2. bendme

    bendme New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2009
    Сообщения:
    179
    Ты изменений то в файле своем hello.com не делаешь никаких. Ты всего-лишь изменяешь строку в копии этого файла в памяти запущенной программы, и всё это бесследно исчезает после завершения проги.
     
  3. pashe4ka13

    pashe4ka13 New Member

    Публикаций:
    0
    Регистрация:
    4 окт 2010
    Сообщения:
    263
    Я в вашей второй программе не вижу настройку сегментных регистров, может в этом проблемма?
    assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
     
  4. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    bendme Спасибо огромное! А как же функция 3Eh, сохраняющая его? Ведь функция с добавлением в конец файла (40h) в этом случае работает? И что надо тогда сделать, чтобы изменения-таки внести?

    pashe4ka13 в самом верху она.
     
  5. bendme

    bendme New Member

    Публикаций:
    0
    Регистрация:
    10 мар 2009
    Сообщения:
    179
    Функция 3Еh только закрывает файл http://www.codenet.ru/progr/dos/int_0026.php А запись в файл идет через функцию 40h. Еще понадобится 42-ая функция для установки места, в которое будет записываться инфа в открытый файл. А читать файл вабще не требуется в этой задаче.
     
  6. _mm_

    _mm_ New Member

    Публикаций:
    0
    Регистрация:
    28 дек 2010
    Сообщения:
    45
    bendme, огромное спасибо! По Вашим словам, будет работать примерно так (и работает):

    Код (Text):
    1. .286
    2.  
    3. CSEG segment
    4. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
    5. org 100h
    6.  
    7. begin:
    8.  
    9. ;Данная программа будет обновлять файл
    10. ;hello.com
    11.  
    12. ;Первоначально откроем файл RW
    13. mov ax,3D02h
    14. mov dx,offset File_name
    15. int 21h
    16. jc Message_bad
    17.  
    18. ;Если файл существует, сохраняем номер файла
    19. mov Handle,ax
    20. mov bx,ax
    21.  
    22.  
    23.  
    24. ;Устанавливаем указатель с начала файла +9h
    25. mov dx,9h
    26. mov cx,0h
    27. mov ax,4200h
    28. int 21h
    29.  
    30. ;Записываем 16 символов (в т.ч.$) из смещения New_phrase по адресу,
    31. ;указанному выше
    32. mov ah,40h
    33. mov dx,offset New_phrase
    34. mov cx,16
    35. int 21h
    36.  
    37.  
    38. ;Подпрограмма успешного вывода строки и выхода
    39. Message_ok:
    40. ;Сначала сохраним файл, восстановив bx
    41. mov bx,Handle
    42. mov ah,3Eh
    43. int 21h
    44. ;Выводим строку
    45. mov ah,9
    46. mov dx,offset Mess_ok
    47. int 21h
    48. int 20h
    49.  
    50. ;Подпрограмма безуспешного вывода строки и выхода
    51. Message_bad:
    52. mov ah,9
    53. mov dx,offset Mess_bad
    54. int 21h
    55. int 20h              
    56.  
    57. ;Имя файла
    58. File_name db 'hello.com',0,'!$'
    59.  
    60. ;Успешное сообщение
    61. Mess_ok db 'Файл обновлён. Всем спасибо.$'
    62.  
    63. ;Плохое сообщение
    64. Mess_bad db 'Файл не найден. Поместите hello.com в каталог с программой.$'
    65.  
    66. ;Определяем переменную
    67. Handle dw 0FFFFh
    68. ;Новая фраза, которая заменяет Hello, world
    69. New_phrase db 'Goodbye, world!$'
    70.  
    71. ;Переменная для вычисления длины файла
    72. Finish equ $
    73.  
    74. CSEG ends
    75. end begin
    У меня же интерес именно в применении rep movsb. Но правильно я понимаю, если всё же его применять, моя программа станет выглядеть следующим образом (используется и 40h, и 42h):

    Код (Text):
    1. .286
    2.  
    3. CSEG segment
    4. assume cs:CSEG, ds:CSEG, es:CSEG, ss:CSEG
    5. org 100h
    6.  
    7. begin:
    8.  
    9. ;Данная программа будет обновлять файл
    10. ;hello.com
    11.  
    12. ;Первоначально откроем файл RW
    13. mov ax,3D02h
    14. mov dx,offset File_name
    15. int 21h
    16. jc Message_bad
    17.  
    18. ;Если файл существует, сохраняем номер файла
    19. mov Handle,ax
    20. mov bx,ax
    21.  
    22. ;Чтение в память
    23. mov ah,3Fh
    24. ;Определяем количество читаемых байт (напр. 65000)
    25. mov cx,0FDE8h
    26. ;По адресу памяти за нашей программой
    27. mov dx,offset Finish
    28. int 21h
    29.  
    30.  
    31. ;Файл в нашей памяти. Строка Hello, world находится в db
    32. ;в смещении 109h от начала программы hello, т.е. через 9 байт
    33. ;У нас она располагается тоже через 9 байт, но после конца (Finish equ $)
    34. ;Определим её настоящий адрес
    35.  
    36. add dx,9h
    37.  
    38. ;Переносим 15 букв c адреса смещения переменной New_phrase
    39. ;на новый адрес dx (конец нашей програмы + 9 байт)
    40.  
    41. mov si,offset New_phrase
    42. mov di,dx
    43. mov cx,16
    44. rep movsb
    45.  
    46. mov dx,0h
    47. mov cx,0h
    48. mov ax,4200h
    49. int 21h
    50.  
    51. mov ah,40h
    52. mov dx,offset Finish
    53. mov cx,25
    54. int 21h
    55.  
    56. ;Смотрим отладчик - файл прочтён и строка в памяти заменилась!
    57.  
    58. ;Подпрограмма успешного вывода строки и выхода
    59. Message_ok:
    60. ;Сначала сохраним файл, восстановив bx
    61. mov bx,Handle
    62. mov ah,3Eh
    63. int 21h
    64. ;Выводим строку
    65. mov ah,9
    66. mov dx,offset Mess_ok
    67. int 21h
    68. int 20h
    69.  
    70. ;Подпрограмма безуспешного вывода строки и выхода
    71. Message_bad:
    72. mov ah,9
    73. mov dx,offset Mess_bad
    74. int 21h
    75. int 20h              
    76.  
    77. ;Имя файла
    78. File_name db 'hello.com',0,'!$'
    79.  
    80. ;Успешное сообщение
    81. Mess_ok db 'Файл обновлён. Всем спасибо.$'
    82.  
    83. ;Плохое сообщение
    84. Mess_bad db 'Файл не найден. Поместите hello.com в каталог с программой.$'
    85.  
    86. ;Определяем переменную
    87. Handle dw 0FFFFh
    88.  
    89. ;Новая фраза, которая заменяет Hello, world
    90. New_phrase db 'Goodbye, world!$'
    91.  
    92. ;Переменная для вычисления длины файла
    93. Finish equ $
    94.  
    95. CSEG ends
    96. end begin
    Сейчас это, конечно, бессмысленно. Но что, если с читаемым файлом проводится (в памяти) множество других операций, а потом требуется его записать - мой алгоритм верен?