Вывод через wsprintf на assemblere

Дата публикации 14 сен 2022 | Редактировалось 16 сен 2022
Многие используют функцию wsprintf(), но не все знают, что в справке msdn есть 2 ошибки, которые могут в один прекрасный день убить ваш софт.
Код (Text):
  1. ; wsprintf( // Фоpматиpует и записывает в буфеp последовательность символов
  2. ;DWORD  lpOut, // Буфеp для пpиема отфоpматиpованных символов
  3. ;DWORD lpFmt, // Стpока упpавления фоpматом
  4. ; ... ); // Массив аpгументов для стpоки упpавления фоpматом
  5. ;==============================================================================
  6. ; В случае успешного завеpшения - число символов в lpOut,
  7. ; не считая 0 , в пpотивном случае - меньше, чем длина lpFmt.
  8. ;==============================================================================
  9. .386 ;
  10. .model flat,stdcall ;
  11. option casemap:none ;
  12. ;==============================================================================
  13. include c:\masm32\include\windows.inc
  14. include c:\masm32\include\kernel32.inc
  15. include c:\masm32\include\user32.inc
  16. includelib c:\masm32\lib\kernel32.lib
  17. includelib c:\masm32\lib\user32.lib
  18. ;==============================================================================
  19. .data ;
  20. ;==============================================================================
  21. lpOut db 255 dup(0) ;Здесь будет храниться результат (lpOut < 1024)!
  22. Message db "Result:",0 ;Заголовок MessageBox
  23. Unicode db 55h,0,6Eh,0,69h,0,63h,0,6Fh,0,64h,0,65h,0,0,0 ;строка в Unicode
  24. ;==============================================================================
  25. ; 1. Простейшие форматы lpFmt = %type
  26. ;==============================================================================
  27. lpFmtc db "%c",0 ;Single character
  28. lpFmtC db "%C",0 ;Single character
  29. lpFmtd db "%d",0 ;Signed decimal integer
  30. lpFmthc db "%hc",0 ;Single character
  31. lpFmthd db "%hd",0 ;Signed short integer
  32. lpFmths db "%hs",0 ;String
  33. lpFmthu db "%hu",0 ;Unsigned short integer
  34. lpFmti db "%i",0 ;Signed decimal integer
  35. lpFmtlc db "%lc",0 ;Single character
  36. lpFmtld db "%ld",0 ;Long signed integer
  37. lpFmtli db "%li",0 ;Long signed integer
  38. lpFmtls db "%ls",0 ;String
  39. lpFmtlu db "%lu",0 ;Long unsigned integer
  40. lpFmtlx db "%lx",0 ;Long unsigned hexadecimal integer
  41. lpFmtp db "%p",0 ;Win2000/XP hexadecimal pointer
  42. lpFmts db "%s",0 ;String
  43. lpFmtS db "%S",0 ;String
  44. lpFmtu db "%u",0 ;Unsigned integer
  45. lpFmtx db "%x",0 ;Unsigned hexadecimal integer
  46. ;==============================================================================
  47. ; 2. Сложные форматы lpFmt = %[-][#][0][width][.precision]type
  48. ;==============================================================================
  49. _lpFmtc db "char: %c",0
  50. _lpFmtC db "%C is char",0
  51. _lpFmtd db "4: %.4d",0
  52. _lpFmthc db "%hc : %04Xh",0
  53. _lpFmthd db "%hd is int.",0
  54. _lpFmths db "%-45hs%8d",0
  55. _lpFmthu db "-%.2hu",0
  56. _lpFmti db "(%i) = %i",0
  57. _lpFmtlc db "%lc*%lc",0
  58. _lpFmtld db "%ld kb/s",0
  59. _lpFmtli db "cool! , %li",0
  60. _lpFmtls db "len 4: %.4ls",0
  61. _lpFmtlu db "<%lu> MHz",0
  62. _lpFmtlx db "hex: %#08lx",0
  63. _lpFmtp db "pointer: %p",0
  64. _lpFmts db "string: %s ,len: %i",0
  65. _lpFmtS db "%S = %u bytes ...",0
  66. _lpFmtu db "int: %u.%u.%u.%u",0
  67. _lpFmtx1 db "hex: %04x-%04x-%04x-%04x",0
  68. _lpFmtx2 db "hex: #%.2lX%.2lX%.2lX",0
  69. _lpFmtx3 db "eax=%0.8X ebx=%0.8X ecx=%0.8X edx=%0.8X esi=%0.8X",13,10, \
  70.                 "edi=%0.8X ebp=%0.8X esp=%0.8X",0
  71. ;==============================================================================
  72. ; 3. Макрос
  73. ;==============================================================================
  74. lpFmt macro Text ;
  75.     local szText ;
  76. .data ;
  77. szText byte Text,0 ;
  78. .code ;
  79. exitm <offset szText>   ;
  80. endm ;
  81. ;==============================================================================
  82. .code
  83. start:
  84. ;==============================================================================
  85. ; 1. Примеры использования простейших форматов lpFmt
  86. ;==============================================================================
  87. invoke wsprintf,addr lpOut,addr lpFmtc ,65 ;
  88. call result ; "A"
  89. invoke wsprintf,addr lpOut,addr lpFmtC ,"a" ;
  90. call result ; "a"
  91. invoke wsprintf,addr lpOut,addr lpFmtd ,1 ;
  92. call result ; "1"
  93. invoke wsprintf,addr lpOut,addr lpFmthc,65 ;
  94. call result ; "A"
  95. invoke wsprintf,addr lpOut,addr lpFmthd,1 ;
  96. call result ; "1"
  97. invoke wsprintf,addr lpOut,addr lpFmths,addr Unicode ;
  98. call result ; "U"
  99. invoke wsprintf,addr lpOut,addr lpFmthu,1 ;
  100. call result ; "1"
  101. invoke wsprintf,addr lpOut,addr lpFmti ,1 ;
  102. call result ; "1"
  103. invoke wsprintf,addr lpOut,addr lpFmtlc,65 ;
  104. call result ; "A"
  105. invoke wsprintf,addr lpOut,addr lpFmtld,5872h ;
  106. call result ; "22642"
  107. invoke wsprintf,addr lpOut,addr lpFmtli,1 ;
  108. call result ; "1"
  109. invoke wsprintf,addr lpOut,addr lpFmtls,addr Unicode ;
  110. call result ; "Unicode"
  111. invoke wsprintf,addr lpOut,addr lpFmtlu,65 ;
  112. call result ; "65"
  113. invoke wsprintf,addr lpOut,addr lpFmtlx,01A2Bh ;
  114. call result ; "1a2b"
  115. invoke wsprintf,addr lpOut,addr lpFmtp ,65h ;
  116. call result ; "00000065"
  117. invoke wsprintf,addr lpOut,addr lpFmts ,addr Message ;
  118. call result ; "Result:"
  119. invoke wsprintf,addr lpOut,addr lpFmtS ,addr Unicode ;
  120. call result ; "Unicode"
  121. invoke wsprintf,addr lpOut,addr lpFmtu ,100 ;
  122. call result ; "100"
  123. invoke wsprintf,addr lpOut,addr lpFmtx ,01A2Bh ;
  124. call result ; "1a2b"
  125. ;==============================================================================
  126. ; 2. Примеры использования сложных форматов lpFmt
  127. ;==============================================================================
  128. invoke wsprintf,addr lpOut,addr _lpFmtc ,65
  129. call result
  130. invoke wsprintf,addr lpOut,addr _lpFmtC ,"a"
  131. call result
  132. invoke wsprintf,addr lpOut,addr _lpFmtd ,1
  133. call result
  134. invoke wsprintf,addr lpOut,addr _lpFmthc ,65,65
  135. call result
  136. invoke wsprintf,addr lpOut,addr _lpFmthd ,1
  137. call result
  138. invoke wsprintf,addr lpOut,addr _lpFmths ,addr Unicode,571
  139. call result
  140. invoke wsprintf,addr lpOut,addr _lpFmthu ,1
  141. call result
  142. invoke wsprintf,addr lpOut,addr _lpFmti ,1,1
  143. call result
  144. invoke wsprintf,addr lpOut,addr _lpFmtlc ,65,56
  145. call result
  146. invoke wsprintf,addr lpOut,addr _lpFmtld ,5872h
  147. call result
  148. invoke wsprintf,addr lpOut,addr _lpFmtli ,1
  149. call result
  150. invoke wsprintf,addr lpOut,addr _lpFmtls ,addr Unicode
  151. call result
  152. invoke wsprintf,addr lpOut,addr _lpFmtlu ,666
  153. call result
  154. invoke wsprintf,addr lpOut,addr _lpFmtlx ,01A2Bh
  155. call result
  156. invoke wsprintf,addr lpOut,addr _lpFmtp ,65h
  157. call result
  158. invoke wsprintf,addr lpOut,addr _lpFmts ,addr Message,sizeof Message-1
  159. call result
  160. invoke wsprintf,addr lpOut,addr _lpFmtS ,addr Unicode,sizeof Unicode
  161. call result
  162. invoke wsprintf,addr lpOut,addr _lpFmtu ,100
  163. call result
  164. invoke wsprintf,addr lpOut,addr _lpFmtx1 ,01A2Bh
  165. call result
  166. invoke wsprintf,addr lpOut,addr _lpFmtx2 ,01A2Bh
  167. call result
  168. invoke wsprintf,addr lpOut,addr _lpFmtx3 ,eax,ebx,ecx,edx,esi,edi,ebp,esp
  169. call result
  170. ;==============================================================================
  171. ; 3. Пример c использованием макроса
  172. ;==============================================================================
  173. invoke wsprintf,addr lpOut,lpFmt("%ld kb/s"),5872h
  174. call result
  175. invoke wsprintf,addr lpOut,lpFmt("Alert, sindrom vachtera detected, %li"),1
  176. call result
  177. ;==============================================================================
  178. invoke ExitProcess,0
  179. ;==============================================================================
  180. ; Вывод результата
  181. ;==============================================================================
  182. result proc
  183. invoke MessageBox,0,addr lpOut,addr Message,MB_OK
  184. ret
  185. result endp
  186. ;==============================================================================
  187. end start

5 417
who_know777

who_know777
Member

Регистрация:
29 мар 2021
Публикаций:
2

Комментарии


      1. alex_dz 19 сен 2022
        Спасибо, познавательная статья

        на самом деле проблема для ml64 представляет вот тот макрос, на него и ругаеться

        ;==============================================================================
        ; 3. Макрос
        ;==============================================================================
        lpFmt macro Text ;
        local szText ;
        .data ;
        szText byte Text,0 ;
        .code ;
        exitm <offset szText> ;
        endm ;


        конкретно при использовании макроса

        invoke wsprintf,addr lpOut,lpFmt("%ld kb/s"),5872h

        получаем

        Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
        Copyright (C) Microsoft Corporation. All rights reserved.
        Assembling: wsprn.asm
        ***************************
        ERROR Unknown argument type -> offset ??0199
        ***************************
        wsprn.asm(174) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(174): Main Line Code
      2. who_know777 19 сен 2022
      3. alex_dz 19 сен 2022
        Спасибо за код,
        Пробую адаптировать на Masm64, получаю такие ошибки, просьба подсказать в чем дело
        ----------
        Microsoft (R) Macro Assembler (x64) Version 14.00.24210.0
        Copyright (C) Microsoft Corporation. All rights reserved.

        Assembling: wsprn.asm
        ***************************
        ERROR Unknown argument type -> offset ??0172
        ***************************
        ***************************
        ERROR Unknown argument type -> offset ??017B
        ***************************
        wsprn.asm(166) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(166): Main Line Code
        wsprn.asm(168) : error A2052:forced error
        REGISTER(22): Macro Called From
        procedure_call(11): Macro Called From
        invoke(1): Macro Called From
        wsprn.asm(168): Main Line Code
      4. who_know777 16 сен 2022
        Мало букв?
      5. TermoSINteZ 16 сен 2022
        Вы серьезно думаете, что это статья?