1

当谈到 FASM 时,我是一个新手,而且对 ASM 来说一般来说还是很新的,但我正在尝试比较存储在“变量”中的两个字符串:user_inputexit_cmd

目前,它组装得很好,但是当我在提示中输入任何内容时它会崩溃。是的,我的代码很乱,我试图完成的任务似乎超出了我所知道的 ASM 水平,但我已经用其他语言完成了它,所以我正在用 ASM 进行尝试。

如果字符串匹配,您可以看到我正在使用宏CompareStrings(来源未知;它不是我的)设置EAX为 1,但是当我EAX使用 1CMPJE标签进行比较时,它拒绝工作。有什么帮助吗?

这是错误的代码:

format PE console
;win32a.inc, win32w.inc, win64a.inc and win64w.inc
include 'win32w.inc'
entry main

; Define macros for things like printing strings ('print') and pausing (well, waiting for the user to press enter ('pause'))
macro print str {
      push str
      call [printf]
      push 0
}
macro pause {
      invoke system,'pause>nul'
}
macro getinput prompt {
      print prompt
      invoke gets,user_input
}
macro CompareStrings str1, str2
{
      lea edi, [str2]               ; edi -> address of string2
      dec edi                       ; edi = edi - 1
      .lab1:                        ; loop through all chars and compare each of them
      inc edi                       ; ds:di --> next character in string2
      lodsb                         ; al = next char from string1. loadsb increments si automatically
      cmp [edi], al                 ; compare characters
      jne .notfound                 ; jump out of the loop if they're unequal
      cmp al, 0                     ; chars are equal, but make sure we compared the entire string
      jne .lab1                     ; if not, continue the loop
      mov eax, 1                    ; else: strings are equal -> eax = 1
      ret                           ; return; result: strings are equal
      .notfound:                    ; chars are not equal
      mov eax, 0                    ; unequal -> eax = 0
      ret                           ; return; result: strings are not equal
}

section '.text' code readable executable

main:
        print header_msg
        jmp input_loop

input_loop:
        getinput cmd_prompt
        print newline
        CompareStrings user_input,cmd_exit
        cmp eax, 1
        je exit_cmd
        jne input_loop

exit_cmd:
        print header_msg
        ret

section '.data' data readable writable
        header_msg    db      "Basic Programming Language in ASM | Version 0.0.1",13,10,0
        cmd_prompt    db      "> ",0
        newline       db      "",13,10,0
        user_input    db      "",0dh,0ah,0
        chrarr        db      '%s',0dh,0ah,0
        cmd_exit      db      'exit',0

section '.idata' import data readable

library msvcrt,"msvcrt.dll"

import msvcrt,\
       puts,"puts",\
       getchar,"getchar",\
       exit,"exit",\
       printf,"printf",\
       scanf,"scanf",\
       system,"system",\
       gets,"gets"
4

1 回答 1

1

这个程序有很多问题,它崩溃并不奇怪。

问题 1

您没有为输入的字符串分配足够的空间。使用rb指令分配一些足够大的空间来处理您的输入:

user_input  rb  1024

将其放在数据部分的末尾,以免在结果可执行文件中发生。

问题 2

我不知道必须如何使用 CPP 库,但可能调用约定不是 STDCALL 并且参数不完全是这些。例如gets可能需要某种 CPP 自扩展字符串,而不是简单的缓冲区地址。否则很容易溢出缓冲区,没有办法检查这样的问题。

因此,最好使用普通的 WinAPI - ReadFile 和 WriteFile 来读取和写入控制台。

问题 3

在上述背景下,这是吹毛求疵,但无论如何:

  push str
  call [printf]
  push 0

push 0在这里看起来很奇怪。应该做什么?

问题 4

你的风格。尝试在不使用“{”和“}”字符的情况下实现这个程序。它将帮助您更好地理解汇编语言。

于 2013-10-11T23:31:42.860 回答