Bash - 如何计算指令数量?

时间:2010-11-29 15:57:09

标签: regex linux bash assembly build

我有许多* .s程序集文件。我想计算它们包含多少指令。例如,要计算所有 mul 指令,我会这样做:

cat *.s | grep -P '\t'"mul" | wc -l

给出了所有mul指令的复合数。

我希望输出如下:

mul: 893
add: 12054
sub: 2356
...

问题是目标平台不支持指令表。每个目标平台都有不同的指令集。必须从现有的程序集文件中推导出支持的指令。我可以在没有Perl / Python代工厂的情况下在Bash中完成吗?

5 个答案:

答案 0 :(得分:5)

你可以像这样得到所有这些:

grep -hP '^[ \t]+[a-z]*' *.s | sed 's/^[ \t]\+\([a-z]*\).*/\1/' | sort | uniq -c

编辑:我将其更改为使用SiegeX提供的示例。

输出:

1 call
6 mov
1 push
1 ret
2 syscall
2 xor

答案 1 :(得分:5)

假设您的说明都是通过使用空格来缩进其他代码(选项卡没问题),那么这个awk 1-liner将起作用:

awk '/^[[:space:]]+/{a[$1]++}END{for(op in a){print op,a[op]}}' /path/to/*.s

输入

$ cat asm.s
section .text
global _start, write
write:
  mov al,1 ;write syscall
  syscall
  ret
_start:
  mov rax,0x0a68732f6e69622f
  push rax
  xor rax,rax
  mov rsi,rsp
  mov rdi,1
  mov rdx,8
  call write

exit: ; just exit not a function
  xor rax,rax
  mov rax,60
  syscall

输出

$ awk '/^[[:space:]]+/{a[$1]++}END{for(op in a){print op,a[op]}}' ./*.s
push 1
xor 2
ret 1
mov 6
syscall 2
call 1

答案 2 :(得分:1)

没有任何外部工具的Bash 4:

declare -A c;while IFS=$'\n' read -r t;do [[ ! $t =~ ^[[:space:]] ]] && continue;w=($t);((c[${w[0]}]++));done<asm.s;for op in ${!c[@]};do echo $op ${c[$op]};done

要执行多个文件,请将while循环包含在for f in *.s循环中,使用while done,如下所示:done < "$f"或者执行while done之类的操作这个:done < <(cat *.s)而不是for f

稍微缩短每行上的第一个单词而不考虑缩进:

declare -A c;while read -ra t;do [[ $t ]]&&((c[${t[0]}]++));done<asm.s;for op in ${!c[@]};do echo $op ${c[$op]};done

但是,它比其他答案更长。

答案 3 :(得分:0)

仅仅是为了它,SiegeX在Perl中的回答

perl -n '/^\s+(\w+)/&&$a{$1}++;END{print map{"$_ $a{$_}\n"}keys%a}' ./*.s

因为“你能做的任何事情我都可以用更接近线路噪音的方式”( - :

答案 4 :(得分:0)

grep -Eo'\ w +'/ source.file | uniq -c