Series Contents


      1. tldr;

See the [Makefile](https://github.com/tonyOreglia/unique-word-counter/blob/master/Makefile) for commands that compile, link, run and debug assembly code on a Docker container. Copied below for convenience:

          1. **build and link assembly**
docker run --rm -v $(current_dir):/app -w /app linux-assembly sh -c "nasm -f elf64 -F dwarf -g $(asm).asm && ld -m elf_x86_64 $(asm).o"
          1. **run executable**

docker run --rm -v "$(current_dir)":/app -w /app linux-assembly sh -c "./a.out"

          1. **debug**

docker run --rm -it --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -v "$(current_dir)":/app -w /app linux-assembly sh -c "gdb a.out"

      1. Figuring Out an Efficient Development Cycle

Now that I've figured out how to get GDB working properly within Docker, I need to understand what my development cycle is going to look like.

I prefer to develop using [VS Code](https://code.visualstudio.com/) rather than something like vim within a Docker container. The question is how can I develop locally and quickly compile, link, run and debug the code on the docker container that is now set up?

The answer came from this helpful [blog post](https://medium.com/travis-on-docker/why-and-how-to-use-docker-for-development-a156c1de3b24). This blog post provides a useful starting point regarding how to leverage an image to build an executable, then run another container to run the executable. Although it does not cover assembly language, it is exactly the sort of workflow we need to use.

The blog post suggests a command like this to handle the build or compiling step (in the case of the blog installing node dependencies): ` docker run --rm -v "$(pwd)":/app -w /app iron/node:dev sh -c 'npm install' But the post does not do a good job of describing what each of these options does, so let's break it down for those of use that are not proficient with Docker: #### __[—rm](https://docs.docker.com/engine/reference/run/#clean-up---rm)__ This is just a build step. We do not need the container up and running once it's been used to prepare the executable. This flag tells Docker to tear down the container once it's finished. #### __[-v](https://docs.docker.com/engine/reference/run/#volume-shared-filesystems) "$(pwd)":/app__ We want to persist the product of the build step. This creates a Docker volume which persists in our local directory after the Docker container is torn down. #### __[-w](https://docs.docker.com/engine/reference/run/#workdir) /app__ Override the working directory that is defined in the base image. #### __iron/ruby__ Base Docker image to use for the build #### __sh -c 'npm install'__ Override command from Docker image. This is the build step in the example. ### Applying this Approach to Compiling, Linking, Running and Debugging Assembly Code on Docker After building an image named linux-assembly with by running the following from the directory containing our [Dockerfile](https://github.com/tonyOreglia/unique-word-counter/blob/master/Dockerfile): bash docker build -t linux-assembly . We can compile and link the assembly code program using with: bash docker run --rm -v "$(pwd)":/app -w /app linux-assembly sh -c "nasm -f elf64 -F dwarf -g hellow.asm && ld -m elf_x86_64 -o hw hellow.o" This produces an executable file (hw) in my local directory. Note that this executable is in elf64 format which will not run on a Mac operating system. We can run the executable on the same Docker image with the command: bash docker run --rm -v "$(pwd)":/app -w /app linux-assembly sh -c "./hw" Lastly, we can debug on the Docker container with the command: bash docker run --rm -it --cap-add=SYS_PTRACE -v "$(pwd)":/app -w /app linux-assembly sh -c "gdb hw" Now I am able to develop locally using VSCode and quickly run the program on the Docker container or debug using GDB on Docker if needed. --- [[Series Contents|(Series) X86–64 Assembly Language Guide]] [[Next >>>|Printing Command Line Arguments]]