assembly 为什么不打印?NASM x86编码

envsm3lx  于 2023-03-18  发布在  其他
关注(0)|答案(1)|浏览(159)

这是它应该打印的内容
输入以某种语言编写的字符串:“如果土拨鼠会扔木头,它会扔多少木头?”
a:2 B:0 c:10 d:6 e:0 f:1 g:0 h:6 i:1 j:0 k:4 l:2 m:1 n:0 o:11 p:0 q:0 r:0 s:0 t:0 u:7 v:0 w:6 x:0 y:0 z:0观察员
然而我的只是打印:输入以某种语言编写的字符串:“如果土拨鼠会扔木头,它会扔多少木头?”
a:2 B:0 c:10 d:6 e:0 f:1 g:0 h:6 i:1 j:0 k:4 l:2 m:1 n:0 o:11 p:0 q:0 r:0 s:0 t:0 u:7 v:0 w:6 x:0 y:0 z:0

%include "asm_io.inc"

section .data
    msg     db      "Enter a string written in some language: ", 0

section .bss
    counters resd    26 ; an array of 26 counters, each storing a 4-byte value
    sorted   resd    26 ; an array of 26 letters, sorted by decreasing number of occurrences
    input    resd   1   ; to store the input character

section .text
    global asm_main

asm_main:
    ; setup
    enter   0, 0
    pusha

    ; print prompt
    mov eax, msg
    call print_string

    ; loop to count characters
    mov ebx, counters
loop:
    call read_char ; read input character
    cmp  eax, 10 ; check if end of input (newline character)
    je end ; if newline character, exit loop
    cmp eax, 97 ; check if lowercase
    jl upper_case ; if less than 97, ignore
    cmp eax, 122 ; check if lowercase
    jg not_alpha ; if greater than 122, check uppercase
    sub eax, 97 ; ASCII value subtract by 97 to get index
    jmp update_counter

lowercase_counter:
    cmp eax, 0
    je next
    add ebx, 4
    dec eax
    jmp lowercase_counter

upper_case:
    cmp eax, 65 ; check if uppercase
    jl not_alpha ;if less than 65, ignore it
    cmp eax, 90 ; check if uppercase
    jg not_alpha ; if greater than 90, ignore it
    sub eax, 65 ; ASCII value subtract by 65 to get index
    jmp update_counter

uppercase_counter:
    cmp eax, 0
    je next
    add ebx, 4
    dec eax
    jmp uppercase_counter

not_alpha:
    ; ignore non-letter characters
    jmp loop

update_counter:
    inc dword [ebx+eax*4]
    mov ebx, counters
    jmp loop

next:
    mov ebx, counters
    jmp loop

end:
    ; print character counts
    mov ebx, counters
    mov ecx, 97
loop2:
    cmp ecx, 122
    jg end2
    mov eax, ecx
    call print_char
    mov eax, 58
    call print_char ; print the colon character
    mov eax, [ebx]
    call print_int
    mov eax, 32
    call print_char
    inc ecx
    add ebx, 4
    jmp loop2

 ; sort letters by decreasing count
    mov eax, sorted
    mov ebx, counters
    mov ecx, 26

outer_loop:
    mov edx, [ebx]
    mov [eax], edx
    add eax, 4
    add ebx, 4
    loop outer_loop

    mov eax, sorted
    mov ebx, 24

sort_loop:
    mov ecx, 0

inner_loop:
    mov edx, [eax]      ; move the value of the first element of the array into edx
    mov ebx, [eax + 4]  ; move the value ofthe second element of the array into ebx
    cmp edx, ebx ; compare the two values
    jge skip_swap ; if the first value is greater than or equal to the second value, skip the swap
    mov [eax], ebx ; move the second value to the first element of the array
    mov [eax + 4], edx ; move the first value to the second element of the array

skip_swap:
    add eax, 4 ; move to the next pair of elements in the array
    loop inner_loop ; repeat until all pairs have been compared and swapped (if necessary)
    dec ebx             ; move to the next element in the array, excluding the last element since it is already sorted
    cmp ebx, 0          ; check if we have reached the beginning of the array
    jge sort_loop       ; if not, repeat the sorting process for the remaining unsorted elements

   ; print sorted letters and their counts
    call print_nl
    mov eax, sorted
    mov ebx, counters
    mov ecx, 26

print_sorted:
    cmp ecx, 0
    jle end2
    mov edx, [eax]
    add eax, 4
    sub ecx, 1
    cmp edx, 0
    je print_sorted   ; skip printing if the count is 0
    add edx, 97
    mov eax, edx
    call print_char
    mov ebx, 58      ; store the ASCII code for ":" in ebx
    call print_char  ; print ":"
    mov eax, [ebx + (edx - 97) * 4] ; retrieve the count using the letter's ASCII value
    call print_int
    call print_nl
    jmp print_sorted

    

end2:
    call print_nl
    popa ; clean up
    mov eax, 0 ; clean up
    leave ; clean up
    ret ; clean up
zyfwsgd6

zyfwsgd61#

为什么不打印?
您的程序没有输出“ocuwhdklamifzyxvtsrqpnjgeb”,因为您在打印完计数器之后已经跳到了末尾。

; print character counts
    mov ebx, counters
    mov ecx, 97
loop2:
    cmp ecx, 122
    jg end2

现在,上面的错误是一种祝福,因为如果排序代码被允许执行,它将被证明包含一个无限循环。您初始化ECX=0,然后使用LOOP指令。这段代码将循环40亿次!
此外,您打算将EBX寄存器用于两个完全不同的目的:一次作为某种计数器,一次作为数组元素。这正是崩溃的组成部分。为什么不使用更多不同的寄存器呢?你还有ESI,EDI和EBP可以玩。
您试图使用计数器对数组副本进行降序冒泡排序。如果不采取预防措施,您将失去与字母表中字母的任何连接
就我个人而言,我会将字符包含在要排序的记录中的某个地方,但只使用实际计数来确定顺序:

; sort letters by decreasing count
  mov  edi, sorted
  mov  esi, counters
  mov  ecx, 00006100h     ; CH='a'
copy_loop:
  mov  eax, [esi]         ; Counter [0,255]
  add  esi, 4
  or   eax, ecx           ; Combine character in AH with count in AL 
  mov  [edi], eax
  add  edi, 4
  add  ecx, 00000100h
  cmp  ecx, 00007A00h     ; CH='z'
  jbe  copy_loop

  mov  ecx, 25            ; ECX is outer loop counter
outer_loop:
  mov  esi, sorted
  mov  edx, ecx           ; EDX is inner loop counter
inner_loop:
  mov  eax, [esi]
  mov  ebx, [esi + 4]
  cmp  al, bl             ; Compare the two COUNTS ONLY
  jge  skip_swap
  mov  [esi], ebx         ; But swap the WHOLE RECORD
  mov  [esi + 4], eax
skip_swap:
  add  esi, 4
  dec  edx
  jnz  inner_loop
  dec  ecx
  jnz  outer_loop

现在,sorted 处的内存如下所示:

11, 'o', 0, 0, 10, 'c', 0, 0, 7, 'u', 0, 0, ...

因此,您需要编写 * 一个简单的循环 *,从每个双字中检索第二个字节,然后将其打印出来。
不要使用当前版本的 print_sorted,它包含许多错误!

相关问题