NASM大会:检查字符串长度+确认字符串只由'0','1'和'2'组成?

时间:2016-12-10 08:48:51

标签: assembly x86 nasm

我对程序集相对较新,我正在尝试创建一个程序,它接受2个命令行参数作为输入(第二个命令行参数是一个字符串)并检查它的长度为1到30之间。它还检查查看字符串是否仅由字符0,1和2组成。任何其他角色,它终止。当我运行程序时,它只输出“分段故障”。从我收集的内容来看,这种情况发生在我处理一部分我不应该搞砸的内存时。我知道我的问题在循环中的某个地方,但我不知道在哪里或为什么。任何有关我的代码错误的建议都将不胜感激。

以下是代码:

%include "asm_io.inc"
global asm_main

SECTION .data
  lenError: db "Length of string must be between 1 and 30 (inclusive).",10,0
  argError: db "Only 2 command line arguments accepted.",10,0
  charError: db "Only characters '0', '1', and '2' are accepted.",10,0

SECTION .text
  global asm_main
  extern strlen
  extern printf

asm_main:
  enter 0,0
  pusha
  mov eax, dword [ebp+8]        ; argc
  cmp eax, dword 2              ; if argc == 2
  jne ERR_ARG
  popa
  mov ebx, dword [ebp+12]
  mov eax, [ebx+4]         ;eax has the string in it now  
  mov ecx, 0               ;initialize a counter
  LOOP1:
    cmp byte[eax], 0       ;end of string
    je DONE
    cmp byte[eax], '0'     ;check if char == 0
    je GO
    cmp byte[eax], '1'
    je GO
    cmp byte[eax], '2'
    je GO
    jmp ERR_CHAR
  GO:
    inc ecx       ; increase counter
    inc eax       ;next position in string
    cmp ecx, 30   
    jg ERR_LEN
  jmp LOOP1

  DONE:
    call print_string      ;there's more to come,
    jmp asm_main_end       ;but i want to find the error first

  ERR_CHAR:
    mov eax, charError
    call print_string
    jmp asm_main_end
  ERR_LEN:
    pop eax
    mov eax, lenError
    call print_string
    jmp asm_main_end

  ERR_ARG:
    mov eax, argError
    call print_string
    jmp asm_main_end

    asm_main_end:
      popa
      leave
      ret

更新:我相信我已将分段错误隔离到asm_main_end,我是如何从程序中终止的?

1 个答案:

答案 0 :(得分:3)

导致分段错误的问题是在函数开头附近popa之后的jne ERR_ARG指令。如果未采用分支,寄存器将从堆栈中弹出,然后再次在asm_main_end处弹出。

asm_main:
  enter 0,0
  pusha
  mov eax, dword [ebp+8]       
  cmp eax, dword 2    
  jne ERR_ARG
  popa                   ; Do not pop here
  ;
  ;
  ;
  asm_main_end:
      popa               ; when popping here
      leave
      ret

然后第二个popa将从堆栈中删除返回地址(除了用不相关的值填充大部分寄存器),使函数返回到最有可能不属于您的程序的任意位置。如果给出错误的参数数量,程序应该正常运行。

顺便说一句:在您的代码中,推送寄存器(除了由enter推送ebp之外)不应该是必要的。