Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
linux nasm程序集查找变量中保留的位数_Linux_Assembly_X86_Nasm - Fatal编程技术网

linux nasm程序集查找变量中保留的位数

linux nasm程序集查找变量中保留的位数,linux,assembly,x86,nasm,Linux,Assembly,X86,Nasm,我正在编写一个程序来打印从0到100的所有数字,我需要找到一个变量(在本例中,变量计数器)的位数 这是我的密码: SECTION .data len EQU 32 SECTION .bss counter resd len digit1 resd len digit2 resd len digit3 resd len SECTION .text GLOBAL _start _start: nop Print: mov eax, 4 mov ebx, 1 mov ecx, counter

我正在编写一个程序来打印从0到100的所有数字,我需要找到一个变量(在本例中,变量
计数器
)的位数

这是我的密码:

SECTION .data
len EQU 32

SECTION .bss
counter resd len 
digit1 resd len
digit2 resd len
digit3 resd len

SECTION .text
GLOBAL _start
_start:
nop

Print:
mov eax, 4
mov ebx, 1
mov ecx, counter
mov edx, len
int 80h 

Set:
mov BYTE [counter], 1

Divide:
; HERE IS WHERE I NEED TO FIND THE LENGTH OF THE VARIABLE COUNTER
; initial division
mov ax, [counter]   ; number we want to print
mov ch, 10    ; we divide by ten to siphon digits
div ch        ; divide our number by 10

; al now has 11, ah has 1
mov dh, ah             ; save the remainder in dh
xor ah,ah
mov ch, 10             ; refill ch with the divisor
div ch                 ; al now has 1, ah now has 1

Move:                     ; now to move our digits to a printable state
mov [digit1], dh      ; first digit is in edx
mov [digit2], ah
mov [digit3], al

Adjust:
add BYTE [digit1], '0'
add BYTE [digit2], '0'
add BYTE [digit3], '0'

Print:
mov eax, 4
mov ebx, 1
mov ecx, digit1
mov edx, len
int 80h

mov eax, 4
mov ebx, 1
mov ecx, digit2
mov edx, len
int 80h

mov eax, 4
mov ebx, 1
mov ecx, digit3
mov edx, len
int 80h

Exit:
mov eax, 1
mov ebx, 0
int 80h
我需要找到长度,这样我就知道要除法多少次,以及要打印变量计数器的位数

我怎样才能知道它有多长


提前感谢对于
0..100范围内的数字,我只需在边界处与伪汇编程序进行比较,如:

    mov ax, [counter]

    mov cx, 3             ; default length
    cmp ax, 100           ; >= 100, use 3
    bge done

    dec cx                ; set length to 2
    cmp val, 10           ; >= 10, use 2
    bge done

    dec cx                ; set length to 1

done:
                          ; cx now holds the digit count.

这实际上最多可以处理999个条件检查,但如果您想扩大范围,还可以在100个条件检查之前添加更多条件检查。

通常这是通过内部缓冲区完成的(实际上堆栈可以:)

将Y=X模10(或Y=X模底),X=X模底除以,直到X=0(并推动每个模Y) 计算分割数,然后从堆栈C中弹出每个结果的次数 并写入输出流

void print_number(int eax, int ebx) {  // ebx = base, eax = number
   int ecx = 0;
   do {
      edx = eax % ebx;
      eax = eax / ebx;
      push(edx);
      ecx++;
   } while (eax);

   while (ecx) {
      pop (eax);
      putch(eax+'0');
      ecx--;
   }
}
关键是,你最终会按照你需要的次数进行分割

一个稍微优化的方法是[再次使用C来鼓励您自己的思考]

void print_number(int a, int base) {
     char string[10];
     static *ptr = string+9;  // points to the last char of string
     *ptr--=0;                // write ending ASCII Zero.
     *ptr='0';
     while (a) {
          *--ptr= '0'+(a % base);  // works for base = 2-10
          a/=base;
     }
     printf("%s",ptr);
}

你能找出为什么这样做有效(或无效)?

Aki给出了一个例子!使用“-S”开关编译它,查看编译器如何处理它-尽管这可能没有太大帮助。:)

你问如何计算数字。我见过代码(来自一本著名的书的作者!),它执行整个
div
循环,直到商为零,只是为了计算数字。然后他做另一个
div
循环来找到他们!做>10、>100、>1000等都可以。但你为什么要知道?您只需保持
div
ing直到商为零,然后计算数字。事实上,通过将商与9进行比较,你可以保存一个
div
div
非常慢!)——如果
be
,你的最后一个数字是al。做额外的
div
更简单,依我看:)

我们得到的余数/数字的顺序是“错误的”。我知道有三种方法可以解决这个问题。我认为“最简单”的方法是将它们推到堆栈上,计算它们的数量,然后按存储/打印它们的顺序将它们弹出,在之前或之后添加“0”

另一种方法是从缓冲区的“后面”开始,然后“向前”工作。这就是Aki的颂歌。对于C兼容代码,返回以零结尾的字符串是可以的,但sys_write不知道以零结尾的字符串,它想知道长度。(没问题,我们可以找到“zstring”的长度)注意,这不会到达缓冲区的开头。如果您不关心“C兼容”代码,您可以返回“我们在缓冲区中到达的位置”和长度-可能在sys_write需要它们的位置
ecx
edx
中。或者您可以将pad分隔到缓冲区的开头。右对齐的数字看起来不错,打印在列中。:)

还有一种方法是继续前进,将它们“向后”放入缓冲区,并在末尾执行“反向字符串”

这些方法都不是很快<代码>div
速度慢,句号!我“拥有”Terje Mathieson(光速解决方案专家)的一些代码,这些代码不使用
div
,但我不理解也不使用它。如果您赶时间,可以在各种优化手册中找到它。:)

如果你把自己限制在100人以内,你不会有多大收获。使用完整的32位寄存器编写例程同样容易(可能更容易),CPU对此也很满意。如果你需要处理负数,那只是稍微复杂一点。如果您在这里找不到示例,您可以在Nasm论坛上找到一些,但是您自己尝试一下是一个有趣的练习,就像您正在做的那样

嗯。。。看。。。保留“太多”内存可能会使程序“膨胀”,但不会造成任何伤害。保留“不够”的内存是一个错误!所以你最好在“太多”方面犯错。还是。。。

第二节数据 len EQU 32 第2节bss 计数器复位透镜 digit1 resd len Digit2Resd len digit3 resd len
... 使用128字节的缓冲区,并为单个数字/字符打印32字节的缓冲区,这似乎太多了。:)

最好的,
弗兰克

如果只是0到100,为什么不在我不太明白你的意思的情况下做一个测试呢。你能举个例子吗?没错。如果想知道位数,可以保留一个内部计数器,也可以减去指针。不管怎么说,我认为人们不应该提前关注那么多的划分,因为它实际上不会加快任何速度。 SECTION .data len EQU 32 SECTION .bss counter resd len digit1 resd len digit2 resd len digit3 resd len